问题描述
我想以下例子; 但无法弄清楚finally块的重要性是什么。 你能告诉我这两个代码示例的执行区别吗? 现实生活中的例子也很有帮助。
样本1:
try{
// some code 1
}catch(Exception ex){
// print exception
}finally{
// some code 2
}
样本2:
try{
// some code 1
}catch(Exception ex){
// print exception
}
// some code 2
1楼
你提出的两个片段有很大的不同,例如当catch
块本身抛出一个异常时, finally
块仍然会被它的语义执行。
这是以下片段打印"Finally!"
,但不是"What about me???"
:
try {
throw null; // throws NullPointerException!
} catch (Exception e) {
int oops = 1/0; // throws ArithmeticException!
} finally {
System.out.println("Finally!"); // still gets executed!
}
System.out.println("What about me???"); // doesn't get executed!
一般来说, try
块的finally
实际上总是被执行。
try
块之后的任何代码都没有这样的保证。
但是,如果我的
catch
块只是一个简单的
仍然无法保证它不会throw
东西。
在例如异常详细消息的构造中,仍然可能出现问题。
即使您尽最大努力保证catch
代码是“安全的”并且try
语句后面的代码将始终执行,那么问题就变成“为什么?”。
为什么finally
要避免,然后再努力复制它的语义?
finally
语义是有保证的,不需要代码的编写者或读者的证据负担。
也正因为如此,它是地道的使用finally
阻止把强制“清理”代码。
使用finally
保证正确性并增强可写性和可读性。
2楼
即使抛出了一个Error
,也会执行finally
块,这不会被示例中的catch
块catch
。
因此,您可以将清理代码放在finally
块中,该块应始终运行,而不管try
和catch
块中的操作结果如何。
请注意,通常catch
块捕获更多特定类型的异常 - 通常只检查异常 - 因此在大多数情况下,上面两个代码示例之间的差异是非常明确的。
更新:您可能会说您的catch
块永远不会抛出异常,因此finally
不需要。
但请注意两件事:
-
这只是代码的当前状态,并且它可以在将来改变 - 你能保证未来的程序员在
catch
块中添加一些可能引发异常的代码,会记得将清理后的代码放到finally
块? -
try-catch-finally
是一种编程习惯用法 ,它使人们更容易阅读代码来理解正在发生的事情。 如果你不使用常用的习语,就会产生误解,从而导致长期的错误。
3楼
您使用finally
块来清理并运行任何应该运行的代码,无论是否抛出(和捕获)异常。
这包括catch
块中的代码。
4楼
当我们想要释放我们在try块中使用的资源时,它会很有用。 因此,在任何情况下执行它们而不丢失的唯一地方是最终阻止。 因为如果抛出异常,java不会执行之后立即执行的代码。 它直接跳转到catch块。
5楼
请注意,您甚至可以在没有catch的情况下尝试finally:
try{
// some code
}finally{
// cleanup code
}
因此,一个示例可能是一种想要将异常传播给调用者的方法,但仍需要清理代码,例如释放外观。
6楼
如果try块中的语句抛出未经检查的异常,则最终将执行块以允许程序员采取相关操作。
7楼
在现实生活中,即使发生异常,finally块也用于关闭打开的资源。 例如,当您读取(或写入)文件,访问数据库等时。
public void readFile(String fileName) {
FileReader fr;
BufferedFileReader bfr;
try {
fr = new FileReader(fileName);
bfr = new BufferedFileReader(fr);
// ...
} catch (IOException ioe) {
// ...
} finally {
// TO ENSURE THAT THE READERS ARE CLOSED IN ALL CASES
if (bfr != null) {
try {
bfr.close();
} catch (IOException ignoredIOE) {}
}
if (fr != null) {
try {
fr.close();
} catch (IOException ignoredIOE) {}
}
}
}