- 作者:zhaozj
- 发表时间:2020-12-23 10:56
- 来源:未知
概要 Java 提供了一个丰富的异常处理框架,但是许多程序员发现:跳过这个丰富的异常处理框架只使用类属Exceptions要容易得多。本文探讨了产生、捕捉和忽视类属Exceptions的风险,并为处理复杂软件项目内的一般的复杂异常建议了最好的处理方法。
在最近的一个项目中,有一块代码实现源代码的清除。因为它有许多不同的调用,很有可能会产生六个不同的异常。原来的程序员在试图简化代码(或者保存键入程序)之后宣告:该程序还不止产生6个不同的异常。这就使得代码调用必须包装在一个可以捕捉Exception 的try/catch 块中。该程序员确定:因为该代码用于清除源代码,失败并不重要,所以catch 块为空,就好像系统关闭了一样。 很明显,这不是最好的编程解决方法,但是好像也看不出有什么大的错误,除了在源代码的第三行有一个小小的逻辑问题:
Listing 1. Original cleanup code private void cleanupConnections() throws ExceptionOne, ExceptionTwo { for (int i = 0; i < connections.length; i++) { connection[i].release(); // Throws ExceptionOne, ExceptionTwo connection[i] = null; } connections = null; } protected abstract void cleanupFiles() throws ExceptionThree, ExceptionFour; protected abstract void removeListeners() throws ExceptionFive, ExceptionSix; public void cleanupEverything() throws Exception { cleanupConnections(); cleanupFiles(); removeListeners(); } public void done() { try { doStuff(); cleanupEverything(); doMoreStuff(); } catch (Exception e) {} } |
在代码的另一个部分,connections 排列没有初始化,直到第一个连接创建为止。但是如果连接没有创见,那么连接排列则为null 。所以在某些情况下,对connections[i].release()的调用将产生NullPointerException。这也是一个相对容易的解决方法。只要添加一个对connections != null的检查。 但是,并没有报告异常。cleanupConnections()产生一个异常, cleanupEverything()又产生一个异常,最后异常被done()捕捉到。done()方法对一场不做任何处理,甚至也不记录一下。因为 只能通过done()调用cleanupEverything() ,所以看不到异常。因此代码也没有得到解决。 因此,在这个失败案例中,没有调用cleanupFiles()和removeListeners() 方法(所以它们的资源没有释放),也没有调用doMoreStuff(),这样done()中的最终处理没有完成。更糟糕的是,系统关闭时没有调用done();相反的,程序只调用done()来完成每个事务。所以每个事务中的资源都漏掉了。 这个问题无疑是一个主要的问题:错误没有报告,资源遗漏。但是代码本身似乎毫无问题,并且从代码的编写方式看,这个问题难于回溯。但是,应用几个简单的指导方针,就可以发现并解决问题: · 不忽视异常 · 不捕捉类属Exception · 不产生类属Exception