Best practices for Exception Handling

public void consumeAndForgetAllExceptions(){
    try {
        ...some code that throws exceptions
    } catch (Exception ex){
        ex.printStacktrace();
    }
}

一旦异常被抛出,正常程序执行将被挂起并且控制权将被转向catch块,catch块捕获异常后仅仅抑制它,catch块执行之后继续程序的执行,好像什么事情都没有发生。

public void someMethod() throws Exception{
}

空的函数体怎么能抛出一个异常呢?Java语言并没有阻止你这么做,但是最近我经常遇到类似的代码,函数体抛出了异常,但是并没有代码去产生这样的异常。

如果没有正确的使用,异常可能会消耗过多的内存和CPU的资源去创建、抛出、捕获异常。如果过度使用,会让代码难以阅读并且使用这样的API会让人感到沮丧。调用者代码通过忽略异常或者抛出异常来绕开这个问题,就像我们上面举的那两个例子。

 

三种情况:

1. 程序错误引起的异常:例如NullPointerException 以及 IllegalArgumentException,客户端通常不能对这类程序错误做任何事情。

2. 调用端代码错误引起的异常:调用端错误使用API,调用端可以利用这些异常信息建立程序。

3. 资源加载失败引起的异常:例如内存耗尽并且网络连接失败,调用端可以过会重试或者打印资源加载失败的错误信息然后停止程序的运行。

 

Java中异常的类型:

Checked Exceptions:继承自Exception类的Exceptions都是checked exceptions。调用端代码必须处理由API抛出的checked exceptions,或者在一个catch块中抛出该异常。

UnChecked Exceptions:RuntimeException也继承自Exception,然而所有继承自RuntimeException的异常都得到了特殊对待,调用端代码也没有必要去处理他们。

 

我们经常使用checked exceptions同时很少使用unchecked exceptions,我们还真的想知道checked exceptions真正的价值何在,可能这主要是因为java是第一个采用checked exceptions的面向对象语言,C++和C#根本没有checked exceptions,都是unchecked exceptions。

 

从底层抛出的checked exceptions强制要求高层调用者做catch或者throws操作。但是如果调用者没有能力有效地处理这个异常,那么调用端就承担不必要的负担,调用者尝试使用空的catch处理块或者直接将异常再次抛出去,实际,就是在客户机上搁置了这个异常。

 

checked exceptions 经常被人指控破坏了封装。

public List getAllAccounts() throws
    FileNotFoundException, SQLException{
    ...
}

这个getAllAccounts()抛出了两个checked exceptions,方法的调用者必须精确地处理这两个异常,尽管他们并不知道文件和数据库加载失败该怎么办,而且他们也没有义务去解决这样的异常,这样造成了调用者和被调用者之间的一种紧耦合。

 

设计API的最佳实践:

1.

更多的对于程序出现的错误,我们选择采用unchecked exceptions,因为他不强制调用端必须处理异常。Java提供了很多unchecked exceptions,所以最好直接使用Java提供的unchecked exceptions而不要用自己创建的,这样可以让代码更容易理解,同时避免内存的占用。

 

2.

保证封装性。

不要让特定实现的checked exceptions抛入更高层,例如不要让SQLException传递到业务层,业务层不需要知道SQLException。

如果非要处理,有两种方法:

① 如果客户端想从这个异常中恢复过来,可以将SQLException转化为另一种checked exception。

② 如果客户端代码无法处理这个异常,可以将SQLException转化为一种unchecked exception。

 

当调用端的代码无法处理类似于SQLException这样的异常的时候,不要犹豫了,直接把它转化为uncheked exceptions,除非你很有自信业务层能在出现这样的异常后得到一些恢复。

 

3.

当对于调用端来说异常信息没有意义,可以尝试创建自定义的exception。

 

4.

。。。 。。。 。。。 。。。

 

使用异常的最佳实践:

  • 使用完资源,自己清理干净
  • 不要使用异常来控制流程
  • 不要忽视异常
  • 不要捕获顶级异常 因为unchecked exceptions也继承于exception
  • 打印异常就打印一次

 

翻译完成 源链接:http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html 感谢这篇文章 让我对异常的处理有了比较深刻的认识!

 

所以 我也总结自己的几句话,也是大家经常犯的问题!

可以处理就处理 不可以处理就抛运行时异常 不要捕获顶级异常 不要搁置异常不处理 做到这些足够了!

posted on 2013-06-09 22:04  Knuth_档案  阅读(159)  评论(0编辑  收藏  举报

导航