Java异常处理
一、java异常简介
java异常都继承自Throwable类,其中Error类及其子类我们不关心,我们只关心Exception类。Exception类的子类分为两种类型:
1、unchecked exception:RuntimeException类。不需要显示的抛出,可以用try...catch语句处理,也可以不处理。
二、java异常处理最佳实践
1. 当要决定是采用checked 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