在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
之前,之后或之间。
有人可以解释一下吗?
答案 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抛出异常,因为你没有处理异常。