我想以下例子;但无法弄清楚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
答案 0 :(得分:17)
您提供的两个片段有很大不同,例如:当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!
一般来说,finally
块的try
几乎总是被执行。 try
阻止后的任何代码都没有这样的保证。
但是如果我的
catch
块只是一个简单的
仍然无保证它不会throw
。例如,某些东西仍可能出错异常详细信息的构造。
即使你尽最大努力保证catch
代码是“安全的”并且try
语句之后的代码将始终执行,那么问题就变成“为什么?”。为什么要避免使用finally
但是要努力复制它的语义?
finally
语义,不需要代码的编写者或读者的证明负担。正因为如此,使用finally
块来强制“清理”代码是惯用。使用finally
可以保证正确性并增强可写性和可读性。
答案 1 :(得分:8)
即使例如finally
块也被执行抛出Error
,您的示例中的catch
块未捕获该finally
。因此,无论try
和catch
块中的操作结果如何,您都可以将清除代码放在catch
块中,该块应该始终。
请注意,通常catch
块会捕获更具体的异常类型 - 通常只检查异常 - 因此在大多数情况下,上面两个代码示例之间的差异非常明确。
更新:您可能会说您的finally
块永远不会抛出异常,因此不需要catch
。但请注意两件事:
finally
中添加一些可能引发异常的代码吗?阻止,会记得将清理后的代码放入try-catch-finally
块吗?答案 2 :(得分:2)
使用finally
块来清理和运行任何应该运行的代码,无论是否抛出(和捕获)异常。这包括catch
块中的代码。
答案 3 :(得分:1)
当我们想要释放我们在try块中使用的资源时,它会很有用。因此,在任何情况下执行它们而不丢失的唯一地方是最终阻止。因为如果抛出异常,java不会执行之后立即执行的代码。它直接跳转到catch块。
答案 4 :(得分:0)
请注意,您甚至可以在没有捕获的情况下尝试使用:
try{
// some code
}finally{
// cleanup code
}
因此,一个示例可能是一种想要将异常传播给调用者的方法,但仍需要清理代码,例如释放外观。
答案 5 :(得分:0)
如果try块中的语句抛出未经检查的异常,则最终将执行块以允许程序员采取相关操作。
答案 6 :(得分:0)
在现实生活中,即使发生异常,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) {}
}
}
}