`

异常处理之最佳实践(Best Practices for Exception Handling )

 
阅读更多

    关于异常处理最主要的问题是什么时间、怎么使用,在本文将含括一些关于异常处理的最佳实践方案。

 

异常的本质(这里有三种不同的情况会产生并抛出异常):

  1. 程序错误:这种异常时由于程序的错误而产生的(例如,NullPointerException and IllegalArgumentException)。
  2. 代码调用错误:客户端代码试图违反API协议调用接口。如果异常能提供一些有用的信息,客户端可以采取一些替代的行为。例如:解析一个不符合格式要求的XML文档而抛出的异常。如果这个异常能包含一些有用的信息(例如xml文档的那个位置出错),那么客户端就可以利用这些信息来采取回复步骤了。
  3. 资源故障错误:例如系统内存不足,网络连接失败。客户端可以在一段时间后重试操作,或者记录资源失败,停止服务。

 

Java中的异常种类:

在java中定义了两种异常:

  1. Checked exceptions: 继承于exception类的异常是checked exceptions, 客户端代码必须处理从API中抛出的此类异常,可以用catch块来处理,也可以用throw把他抛给外面来处理。
  2. Unchecked exceptions:继承于RuntimeException类的异常是Unchecked exceptions,但是所有继承于RuntimeException的类都得到了特殊对待,将不要求客户代码必须处理他们,因此他们被叫做Unchecked exceptions。

下图展示了NullPointerException的继承关系:他继承RuntimeException,因此是一个Unchecked exceptions.

NullpointerException

 

最佳接口设计实践

  • 当你要决定使用哪种异常的时候,你可以先问问自己“当这种异常发生时,客户端代码可以采取什么行为?”

如果客户端可以根据异常采取一些替代行为来恢复系统运行,那么就用checked exception。反之,如果客户端对异常无能为力(记录日志也算没有任何用处, 这里说的有用措施是可以从异常中恢复系统运行),那么就使用unchecked exception吧。

  • 对异常进行封装。

从来不要让具体实现中的特定异常被抛到外层,例如不要把SQLException从DAO层抛到业务逻辑层,因为业务逻辑不需要知道具体的SQLException是什么,这时我们有两种选择:

  1.  
    1. 如果客户端逻辑需要这些错误信息,那么把SQLException转换成另一种checked exception,即封装。
    2. 如果客户端逻辑不需要这些,那么把SQLException转换成另一种unchecked exception,即封装。

大多数时间里,客户端不能对这些SQLException做任何事情, 所以尽量把它们转换成unchecked exceptions. 看看下面两段代码:

 

  1. public void dataAccessCode(){  
  2.     try{  

  •         ..some code that throws SQLException  
  •     }catch(SQLException ex){  
  •         ex.printStacktrace();  
  •     }  
  • }  
  • public void dataAccessCode(){  
  •     try{  
  •         ..some code that throws SQLException  
  •     }catch(SQLException ex){  
  •         throw new RuntimeException(ex);  
  •     }  
  • }  
如果你确定在业务逻辑层能根据DAO的异常做一些恢复操作,那么你可以把它们转换成更有意义的checked exception。
  • 不要试图去创建任何对客户端来说没有有用信息的自定义异常, 参照下面两段代码:
  1. public class DuplicateUsernameException  
  2.     extends Exception {}  
  3. public class DuplicateUsernameException  
  4.     extends Exception {  
  5.     public DuplicateUsernameException   
  6.         (String username){....}  
  7.     public String requestedUsername(){...}  
  8.     public String[] availableNames(){...}  
  9. }  

 

 

  • 为异常添加文档,方便调用者使用。

异常使用的最佳实践

  • Always clean up after yourself

如果你正在使用数据库连接或者网络连接时,一定要记住释放资源,及时你调用的接口只抛出unckecked exception, 也一定要在使用之后利用try - finally块来释放资源。

  1. public void dataAccessCode(){  
  2.     Connection conn = null;  
  3.     try{  
  4.         conn = getConnection();  
  5.         ..some code that throws SQLException  
  6.     }catch(SQLException ex){  
  7.         ex.printStacktrace();  
  8.     } finally{  
  9.         DBUtil.closeConnection(conn);  
  10.     }  
  11. }  
  12. class DBUtil{  
  13.     public static void closeConnection  
  14.         (Connection conn){  
  15.         try{  
  16.             conn.close();  
  17.         } catch(SQLException ex){  
  18.             logger.error("Cannot close connection");  
  19.             throw new RuntimeException(ex);  
  20.         }  
  21.     }  
  22. }  

 

 

  • 从来不要用异常来做流程控制。

 

生成/收集内存stack traces信息是一件代价高昂的事情,stack trace是用来调试的。在try-catch块时他会自动收集stacktrace信息,降低运行速度,而异常处理只有在异常情况的时候才使用。

  1. public void useExceptionsForFlowControl() {  
  2.     try {  
  3.         while (true) {  
  4.             increaseCount();  
  5.         }  
  6.     } catch (MaximumCountReachedException ex) {  
  7.     }  
  8.     //Continue execution   
  9. }  
  10. public void increaseCount()  
  11.     throws MaximumCountReachedException {  
  12.     if (count >= 5000)  
  13.         throw new MaximumCountReachedException();  
  14. }  

 

 

  • 不要压制/忽略/吃掉异常

 

当一个checked exception从一个API被抛出时,它是在试图告诉你要采取一些必要措施来处理他,如果异常对你来说没有任何意义,那么就把他封装成unchecked exception并抛给上一层,千万不要用catch块{}来忽略/吃掉它,当作什么事都没发生过。

 

  • 不要捕捉顶层的异常

 

事实上,Unchecked exceptions 继承于 RuntimeException 类,而它又是继承Exception类,如果捕捉Exception类的话,同时也捕捉了RuntimeException,这样也同时忽略我们本来要抛给上层的Unchecked exceptions。

  1. try{  
  2. ..  
  3. }catch(Exception ex){  
  4. }  

 

 

 

  • 同一个异常只记录一次(Log exceptions just once)

同一个异常的stack trace被记录多次会给程序员检查原始异常源的日志stack trace带来不必要的麻烦/困惑,而且会带来更大的IO量,所以只记录一次。

 

分享到:
评论

相关推荐

    Microsoft WinCE6.0 Exam Preparation Kit for the Microsoft Certified Technology Specialist (MCTS)

    - Best practices for optimizing the run-time image for different hardware configurations. **6. Developing Multi-threaded System Applications** - Principles of multi-threading and its importance in ...

    UIPATH_RAP_Developer_Advanced(online quiz).docx

    Proper exception handling是自动化项目的关键组件之一,它可以帮助开发者快速地响应和解决项目中的异常问题。 Recovery Abilities 自动化项目的恢复能力是另一个关键组件,它可以帮助项目快速地恢复到异常状态...

    oracle-pl-sql-programming-5th-edition

    Like its predecessors, this fifth edition of Oracle PL/SQL Programming covers language fundamentals, advanced coding techniques, and best practices for using Oracle’s powerful procedural language....

    log4j-tutorial.zip_How To Change It

    This tutorial explains how to set up log4j with email, files and stdout. It compares XML to properties configuration files, ...Furthermore, we explain best practices on logging and exception handling.

    common-sense-c-advice-and-warnings-for-c-and-c-programmers.9781882419005.32087

    The chapter covers best practices for defining and using macros, including the importance of understanding macro expansion. Other topics include avoiding common pitfalls related to preprocessor ...

    vc编程系列之Addison Wesley - Exceptional C++

    1. 异常处理(Exception Handling):C++中的异常处理机制是其强大特性之一,用于在程序中优雅地处理错误。书中详细介绍了何时、如何以及为何要使用try、catch和throw语句,以及如何设计和使用异常安全的代码。 2. ...

    Struts2 权威指南 配套源码 第16章

    6. **异常处理(Exception Handling)**:Struts2提供了一套优雅的异常处理机制,包括全局异常映射和动作级别的异常处理。这部分可能详细阐述如何配置和实现自定义的异常处理器。 7. **国际化...

    Core Java Volume I Fundamentals, 11th Edition

    Master foundational techniques, idioms, and best practices for writing superior Java code Leverage the power of interfaces, lambda expressions, and inner classes Harden programs through effective ...

    Essential Windows Communication Foundation For .NET Framework 3.5

    The authors approach each subject with practical advice and present best practices, tips, and tricks for solving problems. Throughout, you’ll find detailed explanations, solutions for the “pain ...

    PHP Objects, Patterns, and Practice, 4th Edition

    This edition introduces new object relevant features such as traits, reflection extension additions, callable type hinting, improvements to exception handling, and many smaller language enhancements....

    c#图书管理系统源代码.pdf

    9. **最佳实践(Best Practices)**: 虽然这个登录示例简化了实际应用中的许多细节,但在真实的系统中,通常会使用更安全的方法来处理用户认证,例如哈希和盐值对密码进行加密,以及使用参数化查询或存储过程来...

    WCF.Multi-Layer.Services.Development.with.Entity.Framework.4th.Edition

    Apply best practices to your WCF services and utilize Entity Framework to access underlying data storage A step-by-step, practical guide with nifty screenshots to create six WCF and Entity Framework ...

    php高手之路 进阶篇

    3. **错误处理与异常处理 (Error Handling & Exception)**:学会如何优雅地处理错误和异常,可以提高代码的健壮性和可维护性。 4. **设计模式 (Design Patterns)**:如单例、工厂、观察者等模式,能够使你的代码...

    Essential C# 5.0-Englis

    This edition also includes C# Coding Guidelines that call attention to today's best practices for writing C# code. Separate indexes of C# versions 3.0, 4.0, and 5.0 make it easy to find answers ...

    SCJP6 Sun Certificated Programmer for Java 6 Study Guide (Exam 310-065) 英文原版

    - **Best Practices**: Following guidelines for maintainable and efficient code. ### Conclusion The SCJP6 Sun Certified Programmer for Java 6 Study Guide (Exam 310-065) is a comprehensive resource ...

    C#文件加密实例源码.rar

    8. **Best Practices(最佳实践)**:源码可能还展示了如何安全地存储和传递密钥,以及如何利用加密服务提供者(CSP,Cryptographic Service Provider)等安全组件。 通过分析这个实例源码,你可以了解到如何在C#中...

    Mule in Action, 2nd Edition

    Exception handling and transaction management with Mule Chapter 10. Securing Mule Chapter 11. Tuning Mule Part 3: Traveling further with Mule Chapter 12. Developing with Mule Chapter 13. Writing ...

Global site tag (gtag.js) - Google Analytics