未捕获的RuntimeException和finally子句:哪个先来?

时间:2011-11-24 10:09:26

标签: java try-catch-finally runtimeexception

RuntimeException块中抛出try而不会被捕获,而finally子句会调用System.exit()

public static void main(String[] args) {
    try {
        Integer.valueOf("NotANumber");
    } finally {
        System.out.println("finally");
        System.exit(0);
    }
}

输出

finally

如果从最后删除System.exit(0),则输出为

finally
Exception in thread "main" java.lang.NumberFormatException: For input string: "NotANumber"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
    at java.lang.Integer.parseInt(Integer.java:449)
    at java.lang.Integer.valueOf(Integer.java:554)
    at exception.MyExcepTest.main(MyExcepTest.java:20)

“finally”可能出现在NumberFormatException之前,之后或之间。

有人可以解释一下吗?

5 个答案:

答案 0 :(得分:14)

在main方法退出之前肯定会执行finally块,之后由JVM打印堆栈跟踪。

也许堆栈跟踪被打印到System.err,并且两个流以不可预测的方式混合在你的控制台输出中(因为它们基本上同时生成)。

当您“最终”打印到System.err时会发生什么?

答案 1 :(得分:6)

问题是,当抛出异常时...... JVM第一次执行内部finally块的代码然后抛出异常,如果被捕获,它将抛出异常并终止线程。 所以这里当finally.block中存在System.exit(0)时,它立即终止线程,因此JVM没有机会抛出异常。 所以输出就是“终于 “

答案 2 :(得分:3)

最后总是执行块。它由语言保证。如果尝试阻止成功终止或者抛出任何异常,则执行它。

有检查和未检查的例外情况。对于未经检查的异常(运行时和错误),您不必编写catch块。但所有异常都由打印堆栈跟踪的JVM捕获。当你的finally块终止应用程序时,它没有机会打印堆栈跟踪,所以你看不到它。

通常在finally块中退出程序是不好的,因为即使您的代码成功运行它也会退出。更常见的是,通常需要块来进行清理,例如关闭文件,套接字等,而不是更复杂的业务逻辑。

答案 3 :(得分:1)

我们可以使用两个块来尝试捕获并最终。

当抛出任何RunTime异常时(最终之前)执行catch块,最后执行block,不管是否抛出异常。

所以如果你想在抛出异常时做一些事情,那么你可以把它放在catch(Excepion e)块中。

你看到的是JVM在终止程序执行之前执行finally块中写入的任务的责任。

当程序终止时,它默认显示抛出异常的痕迹。

答案 4 :(得分:0)

最后方法总是会在try块中返回语句的情况下执行,但在某些情况下,在try块中抛出错误(运行时内存)并不能保证finally块完全执行。

在你的情况下,finally块始终执行,并且main方法从JVM抛出异常,因为你没有处理异常。