Java异常处理12条军规

摘要: 简单实用的建议。java

Fundebug经受权转载,版权归原做者全部。数据库

在Java语言中,异常从使用方式上能够分为两大类:网络

  • CheckedException
  • UncheckedException

在Java中类的异常结构图以下:性能

  • 可检查异常须要在方法上声明,通常要求调用者必须感知异常可能发生,而且对可能发生的异常进行处理。能够理解成系统正常状态下极可能发生的状况,一般发生在经过网络调用外部系统或者使用文件系统时,在这种状况下,错误是可能恢复的,调用者能够根据异常作出必要的处理,例如重试或者资源清理等。spa

  • 非检查异常是不须要在throws子句中声明的异常。JVM根本不会强制您处理它们,由于它们主要是因为程序错误而在运行时生成的。它们扩展了RuntimeException。最多见的例子是NullPointerException 可能不该该重试未经检查的异常,而且正确的操做一般应该是什么都不作,并让它从您的方法和执行堆栈中出来。在高执行级别,应记录此类异常。debug

  • Error是最为严重的运行时错误,几乎是不可能恢复和处理,一些示例是OutOfMemoryError,LinkageError和StackOverflowError。它们一般会使程序或程序的一部分崩溃。只有良好的日志记录练习才能帮助您肯定错误的确切缘由.设计

在异常处理时的几点建议:日志

1. 永远不要catch中吞掉异常,不然在系统发生错误时,你永远不知道到底发生了什么

catch (SomeException e) {  
    return  null;
}
复制代码

2. 尽可能使用特定的异常而不是一概使用Exception这样太泛泛的异常

public void foo() throws Exception { //错误的作法}
复制代码
public void foo() throws MyBusinessException1, MyBusinessException2 { //正确的作法}
复制代码

一味的使用Exception,这样就违背了可检查异常的设计初衷,由于调用都不知道Exception究竟是什么,也不知道该如何处理。捕获异常时,也不要捕获范围太大,例如捕获Exception,相反,只捕获你能处理的异常,应该处理的异常。即然方法的声明者在方法上声明了不一样类型的可检查异常,他是但愿调用者区别对待不一样异常的。code

3. Never catch Throwable class

​永远不要捕获Throwable,由于Error也是继承自它,Error是Jvm都处理不了的错误,你能处理?因此基于有些Jvm在Error时就不会让你catch住。orm

4. 正确的封装和传递异常**

不要丢失异常栈,由于异常栈对于定位原始错误很关键

catch (SomeException e) {throw  new MyServiceException("Some information: " + e.getMessage());  //错误的作法}
复制代码

必定要保留原始的异常:

catch (SomeException e) {   throw new MyServiceException("Some information: " , e);  //正确的打开方式}
复制代码

5. 要打印异常,就不要抛出,不要二者都作

catch (SomeException e) {   
    LOGGER.error("Some information", e);
    throw e;
}
复制代码

这样的log没有任何意义,只会打印出一连串的error log,对于定位问题无济于事。

6. 不要在finally块中抛出异常

若是在finally中抛出异常,将会覆盖原始的异常,若是finally中真的可能会发生异常,那必定要处理并记录它,不要向上抛。

7. 不要使用printStackTrace

要给异常添加上有用的上下文信息,单纯的异常栈,没有太大意义

8. Throw early catch late

异常界著名的原则,错误发生时及早抛出,而后在得到因此所有信息时再捕获处理.也能够理解为在低层次抛出的异常,在足够高的抽象层面才能更好的理解异常,而后捕获处理。

9. 对于使用一些重量级资源的操做,发生异常时,必定记得清理

如网络链接,数据库操做等,能够用try finally来作clean up的工做。

10. 不要使用异常来控制程序逻辑流程

咱们老是不经意间这么作了,这样使得代码变动丑陋,使得正常业务逻辑和错误处理混淆不清;并且也可能会带来性能问题,由于异常是个比较重的操做。

11. 及早校验用户的输入

在最边缘的入口校验用户的输入,这样使得咱们不用再更底层逻辑中到处校验参数的合法性,能大大简化业务逻辑中没必要要的异常处理逻辑;相反,在业务中不若是担忧参数的合法性,则应该使用卫语句抛出运行时异常,一步步把对参数错误的处理推到系统的边缘,保持系统内部的清洁。

12. 在打印错误的log中尽可能在一行中包含尽量多的上下文

LOGGER.debug("enter A");LOGGER.debug("enter B"); //错误的方式
复制代码
LOGGER.debug("enter A, enter B");//正确的方式
复制代码
相关文章
相关标签/搜索