finally的两种特性:
对于没有垃圾回收和析构函数自动调用机制的语言来说,Java中的finally非常重要。它能使程序员保证:
1、无论异常是否被抛出,finally子句总能被执行。这个特性我们可以用来解决以下问题:Java的异常不允许我们回到异常抛出的地点时,该如何应对?把try块放在循环里,建立了一个“程序继续执行之前必须要达到”的条件。还可以加入一个static类型的计数器之类的装置,使循环在放弃之前能尝试一定的次数,这将使程序的健壮性更上一个台阶。
2、无论try块发生了什么,内存总能得到释放。但Java有垃圾回收机制,所以内存释放不再是问题,而且Java也没有析构函数可供调用。那么,Java在什么情况下才能用到finally呢?
当要把除内存之外的资源恢复到它们的初始状态时,就要用带finally子句。这种需要清理的资源包括:已经打开的文件或网络连接,在屏幕上画的图形,甚至是外部世界的某个开关。
可能导致异常丢失的两种情况:
1、但是如果用某些特殊的方式使用finally子句,会导致异常丢失:
package com.test.exception.lost; public class VeryImportantException extends Exception{ public String toString() { return "A very important exception!"; } } package com.test.exception.lost; public class HoHumException extends Exception { public String toString() { return "A trivial exception"; } } package com.test.exception.lost; public class LostMessage { void f() throws VeryImportantException { throw new VeryImportantException(); } void dispose() throws HoHumException { throw new HoHumException(); } public static void main(String[] args) { try { LostMessage lm = new LostMessage(); try { lm.f(); } finally { lm.dispose(); } } catch(Exception e) { System.out.println(e); } } }
输出中可以看到,VeryImportantException不见了,被finally子句里的HoHumException取代。这是相当严重的缺陷,C++把“前一个一场还没处理完就抛出下一个异常”的情形看成是糟糕的编程错误。也许在Java的未来版本中(此处为JDK1.7)会修正这个问题。
2、一种更加简单的异常丢失情况是从finally子句中返回:
package com.test.exception.lost; public class ExceptionSilencer { @SuppressWarnings("finally") public static void main(String[] args) { try { throw new RuntimeException(); } finally { return; } } }
如果运行这个程序,就会看到及时抛出了异常,也不会产生任何输出。(这里就不贴运行结果的图了,不会有任何输出信息在控制台)
总结:
finally对于保证程序的正确性有很大的用处,但是使用过程中要注意避免以下两种会导致异常丢失的情况(起码在JDK1.7是这样的)
1、在finally子句中抛出异常;
2、在finally子句中返回(return)。