首页 > 代码库 > Java异常-可能会出现异常丢失的情况&finally

Java异常-可能会出现异常丢失的情况&finally

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)。

Java异常-可能会出现异常丢失的情况&finally