8

我很困惑为什么我需要将清理代码(如关闭流)放在一个finally块中。

我读过finallyblock中的代码无论如何都会运行(是否有异常);并且在finally块运行之后,该方法的其余部分将继续。

我的问题是:如果该方法的其余部分必须继续,那么为什么不将清理代码放在函数中的 try/catch 块之后?

4

10 回答 10

11

我的问题是;如果该方法的其余部分必须继续,那么为什么我不在函数中的 try/catch 块之后放置清理代码。

基本上,像这样:

InputStream is = ...
try {
   // use stream
} catch (IOException ex) {
   // report / recover
}
is.close();

但是如果该// use stream部分抛出不同的(例如未经检查的)异常会发生什么?还是// report / recover代码?在任何一种情况下,close()呼叫都不会发生。(如果这些块中有breakorreturn语句怎么办?)

理论上是可以这样实现的。问题是确保代码总是(即总是)运行。如果不捕获一大堆您不应该捕获的异常,就很难做到这一点......而且如果您确实捕获,将无法正确处理。

总而言之,finally是更好的解决方案。

  • 它比您正确处理这种情况所需的卷积更简单,并且
  • 它比典型的三心二意的尝试更可靠。

如果您可以使用finally自动处理的新 Java 7“资源尝试”形式,它会更简单/更可靠。


我要补充一点,您对何时finally执行该子句的描述有点不准确。实际上,finally无论 try 块如何终止,都会执行该块,包括:

  • try方块从末端掉落时,
  • 当它抛出异常时......不管异常是否在这个级别被捕获,或者
  • 当它执行return,continuebreak.

事实上,块不执行的唯一情况是块调用或 JVM 崩溃。(或者如果它进入一个无限循环......)finallytrySystem.exit()

于 2012-08-20T10:09:27.533 回答
3

如果您遇到意外的异常(未捕获和处理)。

于 2012-08-20T10:06:59.487 回答
3

如果抛出未捕获的异常,finally 块将始终运行,但方法中的其余代码将被跳过。

所以如果你把清理代码放在 finally 块之后,如果有异常就不会被调用。

于 2012-08-20T10:07:40.807 回答
1

在 finally 块运行后,该方法的其余部分继续

这仅在没有捕获异常时才成立。如果 try 块内发生异常,将执行 catch 块(如果有此异常),将执行 finally 块,然后如果 catch 块进一步抛出异常,则将控制权交给方法的调用者,而无需在此方法中运行任何进一步的代码。

编辑:澄清 catch 当然必须返回,而不仅仅是吃异常。

于 2012-08-20T10:07:37.200 回答
1

如果Exception发生了,即执行了try块,那么放心,该finally块也会被执行。这只是一个保障选项,而不是假设该方法的其余部分将被执行。

于 2012-08-20T10:08:32.373 回答
1

如果该方法的其余部分必须继续,那么为什么我不在函数中的 try/catch 块之后放置清理代码。

因为您的代码清理与您try执行尝试打开资源等的操作有关,所以从逻辑上讲,它应该作为final子句的一部分,因为它是与您的try.
例如,由于在返回之前必须进行一些处理,因此在 100 行之后关闭文件或连接是没有意义的。
你得到了结果。也不例外,释放资源。最好这样做,finally以便您的代码更干净,因为它总是被执行

于 2012-08-20T10:09:19.103 回答
0

我的问题是;如果该方法的其余部分必须继续,那么为什么不将干净的代码放在函数中的 try/catch 块之后。

您可以这样做,但您必须通过传递需要关闭的对象引用(非 java 资源)在 finally 块中再次调用此函数。因为如果这个函数不是 finally 块并且如果发生任何异常,您的整个方法将被跳过而不关闭非 Java 资源。

您也可以使用 java7 功能 -> try-catch with resources。非java资源会自动关闭。您不需要使用 finally 块。

于 2012-08-20T10:08:50.820 回答
0

可能这里有轻微的误会(或者这是我自己误会了)。无论方法是否在异常情况下退出,都会运行 finally 块,例如

 try {
      throw new Exception();
 }
 finally {
      // Block of code will be called before the method exits as exception is thrown
 }

请注意,此规则几乎没有例外,例如:

 try {
      System.exit(-1);
 }
 finally {
      // Block of code will be called before the method exits as exception is thrown
 }

这是一个(非常危险的)情况,程序将退出而不执行 finally 块。

于 2012-08-20T10:11:05.507 回答
0

finally 块对人和编译器一样好。

不仅要注意编译器,还要注意将阅读您的代码的人。如果清理部分在 finally 块中,那么编辑代码会容易得多。

于 2012-08-20T10:35:36.747 回答
0

最后 Block 将 100% 确定执行 try/catch 将完全执行或不执行。

因此,如果您想释放系统资源,请在 finally 块中编写代码。并返回方法的语句。

于 2012-08-20T11:04:31.020 回答