Java中finally块的要点是什么?

时间:2010-06-30 08:51:18

标签: java exception-handling finally

我想以下例子;但无法弄清楚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

7 个答案:

答案 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!

一般来说,finallytry几乎总是被执行。 try阻止后的任何代码都没有这样的保证。


  

但是如果我的catch块只是一个简单的print语句呢?

仍然无保证它不会throw。例如,某些东西仍可能出错异常详细信息的构造。

即使你尽最大努力保证catch代码是“安全的”并且try语句之后的代码将始终执行,那么问题就变成“为什么?”。为什么要避免使用finally但是要努力复制它的语义?

保证

finally语义,不需要代码的编写者或读者的证明负担。正因为如此,使用finally块来强制“清理”代码是惯用。使用finally可以保证正确性并增强可写性和可读性。

答案 1 :(得分:8)

即使例如finally块也被执行抛出Error,您的示例中的catch块未捕获该finally。因此,无论trycatch块中的操作结果如何,您都可以将清除代码放在catch块中,该块应该始终

请注意,通常catch块会捕获更具体的异常类型 - 通常只检查异常 - 因此在大多数情况下,上面两个代码示例之间的差异非常明确。

更新:您可能会说您的finally块永远不会抛出异常,因此不需要catch。但请注意两件事:

  • 这只是代码的当前状态,并且将来可以更改 - 你能保证未来的程序员在finally中添加一些可能引发异常的代码吗?阻止,会记得将清理后的代码放入try-catch-finally块吗?
  • {{1}}是一个编程习惯用法,它使阅读代码的人更容易理解正在发生的事情。如果你不使用普通的习语,你就会有误解的风险,从而导致长期的错误。

答案 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) {}
        }
    }
}