Java异常处理

一、java异常简介

  java异常都继承自Throwable类,其中Error类及其子类我们不关心,我们只关心Exception类。Exception类的子类分为两种类型:

     1、unchecked exception:RuntimeException类。不需要显示的抛出,可以用try...catch语句处理,也可以不处理。

     2、checked exception:Exception类中除了RuntimeException类的其他类。在编译时在语法上必须处理的异常,因此必须在语句中加上try..catch加以处理或者使用throws抛给函数的调用者处理。

二、java异常处理最佳实践

1 当要决定是采用checked exception还是unchecked exception的时候,你要问自己一个问题,如果这种异常一旦抛出,客户端会做怎样的补救?

  尽量使用unchecked exception来处理编程错误:因为unchecked exception不用使客户端代码显示的处理它们,它们自己会在出现的地方挂起程序并打印出异常信息。 

2 保护封装性

     不要让你要抛出的checked exception升级到较高的层次。例如,不要让SQLException延伸到业务层。业务层并不关心SQLException。你有两种方法来解决这种问题:转变SQLException为另外一个checked exception转变SQLException为一个unchecked exception,如果客户端对这种异常无能为力的话。多数情况下,客户端代码都是对SQLException无能为力的,因此你要毫不犹豫的把它转变为一个unchecked exception如果你有足够的信心恢复它,当SQLException被抛出的时候,你也可以把它转换为一个有意义的checked exception, 但是我发现在大多时候抛出unchecked exception已经足够用了。

3 不要创建没有意义的异常

     不要忘记Exception跟其他的Java类一样,客户端可以调用其中的方法来得到更多的信息。checked exception应该让客户端从中得到丰富的信息。要想让你的代码更加易读,请倾向于用unchecked excetpion来处理程序中的错误。

4 Document exceptions

     你可以通过Javadoc’s @throws 标签来说明(document)你的API中要抛出checked exception或者unchecked exception。然而,我更倾向于使用来单元测试来说明异常。不管你采用哪中方式,你要让客户端代码知道你的API中所要抛出的异常。这里有一个用单元测试来测试IndexOutOfBoundsException的例子:

1 public void testIndexOutOfBoundsException() {
2     ArrayList blankList = new ArrayList();
3     try {
4         blankList.get(10);
5         fail("Should raise an IndexOutOfBoundsException");
6     } catch (IndexOutOfBoundsException success) {}
7 }

  上边的代码在请求blankList.get(10)的时候会抛出IndexOutOfBoundsException,如果没有被抛出,将fail("Should raise an IndexOutOfBoundsException")显示说明该测试失败。通过书写测试异常的单元测试,你不但可以看到异常是怎样的工作的,而且你可以让你的代码变得越来越健壮。

5.总是要做一些清理工作

     如果你使用一些资源例如数据库连接或者网络连接,请记住要做一些清理工作(如关闭数据库连接或者网络连接),如果你的API抛出Unchecked 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 
13 class DBUtil{
14     public static void closeConnection(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 }

  DBUtil是一个工具类来关闭Connection.有必要的说的使用的finally的重要性是不管程序是否碰到异常,它都会被执行。在上边的例子中,finally中关闭连接,如果在关闭连接的时候出现错误就抛出RuntimeException.

6. 不要使用异常来控制流程

下边代码中,MaximumCountReachedException被用于控制流程:

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

  记住,只在要会抛出异常的地方进行异常处理。上边的useExceptionsForFlowControl()用一个无限循环来增加count直到抛出异常,这种做法并没有说让代码不易读,但是它是程序执行效率降低。

7. 不要忽略异常

     当有异常被抛出的时候,如果你不想恢复它,那么你要毫不犹豫的将其转换为unchecked exception,而不是用一个空的catch块或者什么也不做来忽略它,以至于从表面来看象是什么也没有发生一样。

8. 不要捕获顶层的Exception

     unchecked exception都是RuntimeException的子类,RuntimeException又继承Exception,因此,如果单纯的捕获Exception,那么你同样也捕获了RuntimeException。

原文链接http://blog.csdn.net/pengchua/article/details/2610324

posted @ 2013-03-27 23:29  小童鞋  阅读(254)  评论(0编辑  收藏  举报