Java 对于清理代码(比如关闭流),finally块真的是必要的吗?
我很困惑,为什么我需要像在Java 对于清理代码(比如关闭流),finally块真的是必要的吗?,java,exception-handling,try-catch-finally,Java,Exception Handling,Try Catch Finally,我很困惑,为什么我需要像在finally块中关闭流那样放置清理代码 我已经读到,finally块中的代码将在任何情况下运行(无论是否存在异常);在finally块运行之后,该方法的其余部分继续 我的问题是:如果该方法的其余部分必须继续,那么为什么不将清理代码放在函数中的try/catch块之后 以防遇到意外异常(未捕获和处理) 在finally块运行之后,方法的其余部分继续 只有在没有发现异常的情况下,这才是正确的。如果在try块内发生异常,将执行catch块(如果此异常有一个),将执行fina
finally
块中关闭流那样放置清理代码
我已经读到,finally
块中的代码将在任何情况下运行(无论是否存在异常);在finally
块运行之后,该方法的其余部分继续
我的问题是:如果该方法的其余部分必须继续,那么为什么不将清理代码放在函数中的try/catch块之后 以防遇到意外异常(未捕获和处理) 在finally块运行之后,方法的其余部分继续 只有在没有发现异常的情况下,这才是正确的。如果在try块内发生异常,将执行catch块(如果此异常有一个),将执行finally块,然后如果catch块进一步抛出异常,将控制权交给方法的调用方,而不在此方法中运行任何进一步的代码
编辑:阐明catch当然必须返回,而不仅仅是吃掉异常。如果抛出未捕获的异常,finally块将始终运行,但方法中的其余代码将被跳过
因此,如果将清理代码放在finally块之后,如果出现异常,它将不会被调用。如果出现
异常,即执行try块,那么,请放心,finally
块也将被执行。这只是一个保护选项,而不是不可靠地假设方法的其余部分将被执行
我的问题是,;如果该方法的其余部分必须继续,那么为什么不将干净的代码放在函数的try/catch块之后呢
可以这样做,但必须通过传递需要关闭的对象引用(非java资源),在finally块中再次调用此函数。因为如果此函数不是finally block,并且如果发生任何异常,则将跳过整个方法,而不关闭非java资源
您还可以使用java7功能->。非java资源将自动关闭。您不需要使用finally块
如果该方法的其余部分必须继续,那么为什么我不将
函数中try/catch块之后的清理代码
因为清理代码与您的try
操作相关,该操作尝试打开资源等,从逻辑上讲,它应该是final
子句的一部分,因为它是与try
相关的最后一个操作
例如,由于在返回之前必须进行一些处理,因此在100行之后关闭文件或连接是没有意义的。
你得到结果了。没有例外,释放资源。最好在finally
中执行,这样您的代码就会更干净,因为它总是被执行
我的问题是,;如果该方法的其余部分必须继续,那么为什么不将清理代码放在函数中的try/catch块之后呢
基本上是这样的:
InputStream is = ...
try {
// use stream
} catch (IOException ex) {
// report / recover
}
is.close();
但是,如果//use stream
部分抛出一个不同的(例如未选中的)异常,会发生什么?还是//报告/恢复
代码?无论哪种情况,close()
调用都不会发生。(如果这些块中有break
或return
语句怎么办?)
从理论上讲,以这种方式实施是可能的。问题在于确保代码始终(即始终)运行。要做到这一点,就很难不捕获一大堆不应该捕获的异常。。。如果你真的抓到了,你就无法正常处理
总之,最后
是更好的解决方案
- 这比正确处理情况所需的卷积要简单,而且
- 这比典型的半心半意的尝试更可靠
如果您可以使用新的Java7“try with resources”表单,其中finally
会自动处理,那么它就更简单/更可靠了
我想补充一点,您对执行finally
子句的时间的描述有点不准确。实际上,无论try块如何终止,都会执行finally
块,包括:
- 当
try
块从末端脱落时
- 当它抛出异常时。。。无论是否在此级别捕获异常,或
- 当执行
返回
、继续
或中断
时
实际上,finally
块不执行的唯一情况是try
块调用System.exit()
或JVM崩溃。(或者如果它进入一个无限循环…也许这里有一个小小的误解(或者是我自己误解了)。无论方法是否在异常条件下存在,都将运行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块中,那么编辑代码将非常容易 最终块将100%确定执行try/catch是否将完全执行
因此,如果您想释放系统资源,请在finally块中编写代码。
还有方法的返回语句。来吧。。。显然是一个错误的陈述!try-catch块后面的代码呢?实际上,忘记了“catch忽略或正确处理异常”。对不起,这是唯一有用的话。干净利落,精力充沛。不仅总是跑步,而且从不跑两次。如果最后没有的话,问题会更糟。
@MarkoTopolnik-是的,尽管有很多