13

A在没有被捕获的情况下被RuntimeException抛出,而子句调用.tryfinallySystem.exit()

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

输出是

finally

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

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

谁能解释一下?

4

5 回答 5

16

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

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

当您也将“finally”打印到 System.err 时会发生什么?

于 2011-11-24T10:13:48.883 回答
7

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

于 2011-11-24T10:20:11.340 回答
3

finally 块总是被执行。它是由语言保证的。如果您尝试块成功终止或抛出任何异常,则执行它。

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

通常在 finally 块中退出程序是不好的,因为即使您的代码成功运行它也会退出。更一般地说,finally 块通常用于清理,如关闭文件、套接字等,而不是更复杂的业务逻辑。

于 2011-11-24T10:16:34.850 回答
1

有两个块可以与 try 一起使用,它们是 catch 和 finally。

当抛出任何 RunTime 异常时(在 finally 之前)执行 catch 块,最后执行 finally 块,无论是否抛出异常。

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

您看到的是 JVM 有责任在终止程序执行之前执行 finally 块中所写的内容。

当程序终止时,默认情况下会向您显示引发的异常的跟踪。

于 2011-11-24T10:22:30.697 回答
0

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

在您的情况下,由于您没有处理异常,因此始终阻止从 JVM 执行 main 方法并抛出异常。

于 2017-06-21T13:20:53.827 回答