这个问题在这里已有答案:
我知道涉及在try / catch / finally块中返回的令人头疼的问题 - finally中的返回始终是方法的返回,即使try或catch块中的返回应该是执行的返回 .
但是,同样适用于System.exit()?例如,如果我有一个try块:
try {
//Code
System.exit(0)
}
catch (Exception ex) {
//Log the exception
}
finally {
System.exit(1)
}
如果没有异常,将调用哪个System.exit()?如果exit是return语句,则System.exit(1)行将始终(?)被调用 . 但是,我不确定退出的行为是否与返回不同 .
代码处于极端情况下,即使不是不可能,也很难再现,因此我无法编写单元测试 . 我今天晚些时候会尝试进行一项实验,如果我得到一些免费的分钟,但我很好奇,也许有人知道答案,可以提供它,或者我无法运行实验 .
6 回答
编号
System.exit(0)
不返回,并且不执行finally块 .System.exit(int)
可以抛出SecurityException
. 如果发生这种情况,将执行finally块 . 并且由于相同的主体从相同的代码库调用相同的方法,因此第二次调用可能会抛出另一个SecurityException
.以下是第二种情况的示例:
包括
catch
在内的简单测试也表明如果system.exit(0)
没有抛出安全异常,它将是最后执行的语句(catch
和finally
根本不执行) .如果
system.exit(0)
确实抛出安全异常,则执行catch
和finally
语句 . 如果catch
和finally
都包含system.exit()
语句,则仅执行这些system.exit()
语句之前的语句 .在上面描述的两种情况中,如果
try
代码属于另一个方法调用的方法,则被调用的方法不返回 .更多细节here(个人博客) .
其他答案已经涵盖了
catch
和finally
块如果System.exit
在不抛出SecurityException
的情况下退出JVM时如何运行,但它们没有显示"try-with-resources"块中对资源的影响:它们是否已关闭?根据JLS, Section 14.20.3.2:
也就是说,在运行
catch
或finally
块之前,资源将是close
d . 即使catch
和finally
没有运行,如果它们以某种方式close
d怎么办?这里有一些代码来证明“try-with-resources”语句中的资源也没有关闭 .
我使用
BufferedReader
的一个简单子类,在调用super.close
之前打印一个语句 .然后我在try-with-resources语句中设置了调用
System.exit
的测试用例 .输出:
因此,不仅
catch
和finally
块不运行,如果System.exit
成功,"try-with-resources"语句将无法获得close
其资源的机会 .finally块将被执行无论什么....即使try块抛出任何throwable(异常或错误).....
只有case finally块不执行...是我们调用System.exit()方法的时候..
它不会执行finally块 . 该程序将在System.exit()语句后终止 .
如果您认为这种行为有问题,并且您需要对
System.exit
调用进行精细控制,那么您唯一能做的就是将System.exit功能包装在您自己的逻辑中 . 如果我们这样做,我们可以最终执行块执行并将资源关闭作为退出流程的一部分 .我正在考虑的是在我自己的静态方法中包装
System.exit
调用和功能 . 在我的exit
实现中,我将抛出Throwable
或Error
的自定义子类,并使用Thread.setDefaultUncaughtExceptionHandler
实现自定义Uncaught异常处理程序来处理该异常 . 因此我的代码变成:这个策略增加了使这个逻辑可测试的“好处”:测试包含我们的“主流”的方法实际上是要求系统退出,我们所要做的就是捕获一个throwable并断言这是write类型 . 例如,我们的业务逻辑包装器的测试可能如下所示:
这种策略的主要缺点是它是一种从异常流中获取功能的方法,这通常会产生意想不到的后果 . 在这种情况下,最明显的一点就是你必须更新你写的任何地方
try { ... } catch(Throwable ex){ /*doesnt rethrow*/ }
. 对于具有自定义执行上下文的库,需要对其进行改进以了解此异常 .上 balancer ,这对我来说似乎是一个很好的策略 . 这里有其他人这么认为吗?
在下面的示例中,如果
System.exit(0)
在异常行之前,程序将正常终止,因此FINALLY将不会执行 .如果
System.exix(0)
是try块的最后一行,这里我们有2个场景当出现异常时,则执行finally块
当异常不存在时,则不执行finally块
.