灵活选择抛出异常

毫无疑问,抛出异常是程序动态执行过程中捕获错误的一种很好的手段,但凡事有益有弊,抛出异常实际上由某种语言在你的代码里面插入了某些代码,在你的代码的基础上,增加了某些控制,这些控制一般比较复杂。其实可以这样认为,抛出的异常越多,越影响程序的执行效率。

所以,应该只在需要捕获异常的地方捕获异常。最好能精确到某个点,如函数内,函数外或者让异常扩散到合适的位置。本文举一个例子,说明一个不恰当捕获异常的范例。


/*
    从 url 列表爬取公司详细信息
*/
private static int foundAndSyncToDB() throws Exception
    {
        DBInit dBInit = new DBInit("db.init");
        if(!dBInit.init())
        {
            System.out.println("数据库初始化失败");
            return 0;
        }
        final Map
   
   
    
     urls = new HashMap
    
    
     
     (){
            {
                put("xxx",1);       //第一个元素是公司 url,第二个元素是该 url 页面的公司的类型
                put("xxxx",1);
                put("xxxxx",1);
                put("xxxxxx",1);
                put("yyy",2);
                put("zzz",3);
                put("zzzzz",3);
            }
        };
        Connection con = dBInit.getConnection();
        PreparedStatement pre;
        pre = con.prepareCall("insert into tbl_company_stock values (?,?,?,?)"); 
        
        int founderCount = 0;
        HashMap
     
     
      
      
       
       > stocks;
        Set
       
       
         keys = urls.keySet(); for (String url : keys) { AutoStockFounderImpl skn = AutoStockFounderImpl.RemoteFileStock(url); stocks = skn.getStocks(); Set 
        
          cols = stocks.keySet(); pre.setInt(3, urls.get(url)); for (String col : cols) { pre.setString(1, col); pre.setString(2, stocks.get(col).get(0)); pre.setString(4, stocks.get(col).get(1)); if(!pre.execute() && 0 != pre.getUpdateCount()) { ++founderCount; } } } pre.close(); return founderCount; } 
         
       
      
      
     
     
    
    
   
   


上面的函数的功能是由从几个公司页面爬取公司详细信息。我们看到,整个函数捕获但不处理异常,直接将异常扩散到外层,由外层去处理。这种写法不会错,但从功能上来讲,不会是我们想要的。为什么呢?在整个函数里面,可能抛出异常的地方有两个,

一是 pre 的初始化处,包括 con.prepareCall 和 pre.set 一系列函数;二是 pre 执行查询处。可以说,一个是静态错误,一个是运行异常。这两者是不同的。只要前者抛出异常,说明必有很多个异常;后者抛出异常,末必有多个。什么意思呢?就是说,pre 构造一旦出错,后面的运行,以及往后再构造也都会出错,所以,只要抛出异常,就应该终止运行,手段有两种:在函数内部捕获到异常后报告并直接退出函数,或者不作任何处理,直接退出函数。而执行查询时发生的运行异常,不能因为发生一次,就不给后面执行机会,直接退出函数,而应该在异常点捕获并处理,让后面还有机会执行查询,上面的代码应该改成如下的样子。


/*
    从 url 列表爬取公司详细信息
*/
private static int foundAndSyncToDB() throws Exception
    {
        DBInit dBInit = new DBInit("db.init");
        if(!dBInit.init())
        {
            System.out.println("数据库初始化失败");
            return 0;
        }
        final Map
   
   
    
     urls = new HashMap
    
    
     
     (){
            {
                put("xxx",1);       //第一个元素是公司 url,第二个元素是该 url 页面的公司的类型
                put("xxxx",1);
                put("xxxxx",1);
                put("xxxxxx",1);
                put("yyy",2);
                put("zzz",3);
                put("zzzzz",3);
            }
        };
        Connection con = dBInit.getConnection();
        PreparedStatement pre;
        pre = con.prepareCall("insert into tbl_company_stock values (?,?,?,?)"); 
        
        int founderCount = 0;
        HashMap
     
     
      
      
       
       > stocks;
        Set
       
       
         keys = urls.keySet(); for (String url : keys) { AutoStockFounderImpl skn = AutoStockFounderImpl.RemoteFileStock(url); stocks = skn.getStocks(); Set 
        
          cols = stocks.keySet(); pre.setInt(3, urls.get(url)); for (String col : cols) { pre.setString(1, col); pre.setString(2, stocks.get(col).get(0)); pre.setString(4, stocks.get(col).get(1)); try { if(!pre.execute() && 0 != pre.getUpdateCount()) { ++founderCount; } } catch (SQLException) { //处理数据库查询发生的异常,不向外层扩散。 } } } pre.close(); return founderCount; } 
         
       
      
      
     
     
    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值