我很困惑为什么我需要将清理代码(如关闭流)放在一个finally
块中。
我读过finally
block中的代码无论如何都会运行(是否有异常);并且在finally
块运行之后,该方法的其余部分将继续。
我的问题是:如果该方法的其余部分必须继续,那么为什么不将清理代码放在函数中的 try/catch 块之后?
我很困惑为什么我需要将清理代码(如关闭流)放在一个finally
块中。
我读过finally
block中的代码无论如何都会运行(是否有异常);并且在finally
块运行之后,该方法的其余部分将继续。
我的问题是:如果该方法的其余部分必须继续,那么为什么不将清理代码放在函数中的 try/catch 块之后?
我的问题是;如果该方法的其余部分必须继续,那么为什么我不在函数中的 try/catch 块之后放置清理代码。
基本上,像这样:
InputStream is = ...
try {
// use stream
} catch (IOException ex) {
// report / recover
}
is.close();
但是如果该// use stream
部分抛出不同的(例如未经检查的)异常会发生什么?还是// report / recover
代码?在任何一种情况下,close()
呼叫都不会发生。(如果这些块中有break
orreturn
语句怎么办?)
理论上是可以这样实现的。问题是确保代码总是(即总是)运行。如果不捕获一大堆您不应该捕获的异常,就很难做到这一点......而且如果您确实捕获,将无法正确处理。
总而言之,finally
是更好的解决方案。
如果您可以使用finally
自动处理的新 Java 7“资源尝试”形式,它会更简单/更可靠。
我要补充一点,您对何时finally
执行该子句的描述有点不准确。实际上,finally
无论 try 块如何终止,都会执行该块,包括:
try
方块从末端掉落时,return
,continue
或break
.事实上,块不执行的唯一情况是块调用或 JVM 崩溃。(或者如果它进入一个无限循环......)finally
try
System.exit()
如果您遇到意外的异常(未捕获和处理)。
如果抛出未捕获的异常,finally 块将始终运行,但方法中的其余代码将被跳过。
所以如果你把清理代码放在 finally 块之后,如果有异常就不会被调用。
在 finally 块运行后,该方法的其余部分继续
这仅在没有捕获异常时才成立。如果 try 块内发生异常,将执行 catch 块(如果有此异常),将执行 finally 块,然后如果 catch 块进一步抛出异常,则将控制权交给方法的调用者,而无需在此方法中运行任何进一步的代码。
编辑:澄清 catch 当然必须返回,而不仅仅是吃异常。
如果Exception
发生了,即执行了try块,那么放心,该finally
块也会被执行。这只是一个保障选项,而不是假设该方法的其余部分将被执行。
如果该方法的其余部分必须继续,那么为什么我不在函数中的 try/catch 块之后放置清理代码。
因为您的代码清理与您try
执行尝试打开资源等的操作有关,所以从逻辑上讲,它应该作为final
子句的一部分,因为它是与您的try
.
例如,由于在返回之前必须进行一些处理,因此在 100 行之后关闭文件或连接是没有意义的。
你得到了结果。也不例外,释放资源。最好这样做,finally
以便您的代码更干净,因为它总是被执行
我的问题是;如果该方法的其余部分必须继续,那么为什么不将干净的代码放在函数中的 try/catch 块之后。
您可以这样做,但您必须通过传递需要关闭的对象引用(非 java 资源)在 finally 块中再次调用此函数。因为如果这个函数不是 finally 块并且如果发生任何异常,您的整个方法将被跳过而不关闭非 Java 资源。
您也可以使用 java7 功能 -> try-catch with resources。非java资源会自动关闭。您不需要使用 finally 块。
可能这里有轻微的误会(或者这是我自己误会了)。无论方法是否在异常情况下退出,都会运行 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 块。
finally 块对人和编译器一样好。
不仅要注意编译器,还要注意将阅读您的代码的人。如果清理部分在 finally 块中,那么编辑代码会容易得多。
最后 Block 将 100% 确定执行 try/catch 将完全执行或不执行。
因此,如果您想释放系统资源,请在 finally 块中编写代码。并返回方法的语句。