zoukankan      html  css  js  c++  java
  • Java 异常处理的误区和经验总结

    一 异常分检测异常非检测异常,异常的应用情景可以概括为以下:

    • 调用代码不能继续执行,需要立即终止。出现这种情况的可能性太多太多,例如服务器连接不上、参数不正确等。这些时候都适用非检测异常,不需要调用代码的显式捕捉和处理,而且代码简洁明了。
    • 调用代码需要进一步处理和恢复。假如将 SQLException 定义为非检测异常,这样操作数据时开发人员理所当然的认为 SQLException 不需要调用代码的显式捕捉和处理,进而会导致严重的 Connection 不关闭、Transaction 不回滚、DB 中出现脏数据等情况,正因为 SQLException 定义为检测异常,才会驱使开发人员去显式捕捉,并且在代码产生异常后清理资源。当然清理资源后,可以继续抛出非检测异常,阻止程序的执行。根据观察和理解,检测异常大多可以应用于工具类中。

    二 不要将异常直接显示在页面或客户端

      何异常都没有实际意义,绝大多数的客户也根本看不懂异常信息,软件开发也要尽量避免将异常直接呈现给用户。

    三 不要用异常污染代码的层次结构

    public Customer retrieveCustomerById(Long id) throw SQLException {
    
     //根据 ID 查询数据库
    
    }

      从设计耦合角度仔细考虑一下,这里的 SQLException 污染到了上层调用代码,调用层需要显式的利用 try-catch 捕捉,或者向更上层次进一步抛出。根据设计隔离原则,我们可以适当修改成:

    public Customer retrieveCustomerById(Long id) {
         try{
    
                //根据 ID 查询数据库
    
         }catch(SQLException e){
    
                //利用非检测异常封装检测异常,降低层次耦合
    
                throw new RuntimeException(SQLErrorCode, e);
    
         }finally{
    
                //关闭连接,清理资源
         }
    }

    四 不要忽略异常

    public void retrieveObjectById(Long id){
       try{
           //..some code that throws SQLException
        }catch(SQLException ex){
         /**
           *了解的人都知道,这里的异常打印毫无意义,仅仅是将错误堆栈输出到控制台。
           * 而在 Production 环境中,需要将错误堆栈输出到日志。
           * 而且这里 catch 处理之后程序继续执行,会导致进一步的问题*/
              ex.printStacktrace();
         }
    }

    异常处理只是将异常输出到控制台,没有任何意义。而且这里出现了异常并没有中断程序,进而调用代码继续执行,导致更多的异常。

    public void retrieveObjectById(Long id){
     try{
        //..some code that throws SQLException
     }
     catch(SQLException ex){
        throw new RuntimeException(“Exception in retieveObjectById”, ex);
     }
     finally{
        //clean up resultset, statement, connection etc
     }
    }

    五 不要将异常包含在循环语句中

      异常处理占用系统资源

    for(int i=0; i<100; i++){
        try{
        }catch(XXXException e){
             //….
        }
    }

    六 不要用Exception捕获所有潜在异常

      这个不用赘述了,Exception太笼统,应该捕获具体的异常。

    七 不要多层次打印相同异常

      同一段异常会被打印 2 次。如果层次再复杂一点,不去考虑打印日志消耗的系统性能,仅仅在异常日志中去定位异常具体的问题已经够头疼的了。

      其实打印日志只需要在代码的最外层捕捉打印就可以了,异常打印也可以写成 AOP,织入到框架的最外层。

    八 异常包含的信息要能充分的定位问题

    九 要多考虑可能的潜在异常,在代码中考虑异常

    十 finally中做资源清理等相关工作  

    十一 请确保在Javadoc中添加一个@throws 声明,并描述可能导致的异常情况。

    十二 异常如果有继关系

      具体的异常卸载前面,抽象的在后面。

    十二 包装异常

      有时最好捕获一个标准异常并将其封装到一个定制的异常中。此类异常的典型例子是应用程序或框架特定的业务异常。这允许你添加额外的信息,并且也可以为异常类实现一个特殊的处理。

    public void wrapException(String input) throws MyBusinessException {
        try {
            // do something
        } catch (NumberFormatException e) {
            throw new MyBusinessException("A message that describes the error.", e);
        }
    }
  • 相关阅读:
    《VC驿站《PE文件格式解析》》
    《逆向分析教程》
    《逆向工程核心原理.pdf【2】》
    《逆向工程核心原理.pdf》
    一个完整的机器学习项目在Python中的演练(一)
    粒子群优化算法(PSO)之基于离散化的特征选择(FS)(三)
    Tensorboard详解(下篇)
    Tensorboard 详解(上篇)
    基于Doc2vec训练句子向量
    使用Keras进行深度学习:(七)GRU讲解及实践
  • 原文地址:https://www.cnblogs.com/liufei1983/p/9033923.html
Copyright © 2011-2022 走看看