【问题标题】:Does a finally block run even if you throw a new Exception?即使你抛出一个新的异常,finally 块也会运行吗?
【发布时间】:2011-05-14 23:21:05
【问题描述】:

即使执行了catch块并抛出了第二个异常,在这段代码中是否会设置someVar

public void someFunction() throws Exception {
    try {
        //CODE HERE
    } catch (Exception e) {
        Log.e(TAG, "", e);
        throw new Exception(e);
    } finally {
        this.someVar= true;
    }
}

【问题讨论】:

  • 因为在某些情况下行为不符合预期,如@GaryF所示
  • 值得注意的是,最终块如果抛出异常或返回,可能无法按预期执行。

标签: java exception-handling


【解决方案1】:

是的,finally 块总是运行...除非:

  • 运行try-catch-finally块的线程被杀死或中断
  • 你使用System.exit(0);
  • 底层 VM 以其他方式销毁
  • 底层硬件在某些方面无法使用

此外,如果您的 finally 块中的方法抛出未捕获的异常,则此后将不会执行任何操作(即,将像在任何其他代码中一样抛出异常)。发生这种情况的一个非常常见的情况是java.sql.Connection.close()

顺便说一句,我猜您使用的代码示例只是一个示例,但要小心将实际逻辑放在 finally 块中。 finally 块用于资源清理(关闭数据库连接、释放文件句柄等),而不是用于必须运行的逻辑。如果它必须在 try-catch 块之前运行,请远离可能引发异常的东西,因为您的意图在功能上几乎肯定是相同的。

【讨论】:

  • “运行 try-catch-finally 块的线程 [...] 被中断”是什么意思?也许该文档措辞不佳,但 Thread.interrupt() 不会导致 finally 块被跳过,无论是从 try 块还是从 catch 块抛出。这是否使用“中断”来表示更暴力的东西,例如 Thread.stop()?
  • @Joe:是的,我认为这里的文档措辞有点糟糕,它们意味着线程活动的普遍中断。
  • @GaryF - 我想你是从 JLS 引用的。 JLS 的措辞有时有点奇怪,但您通常会发现该奇怪术语的含义在文档的其他地方有明确定义。 JLS 是一个规范,其主要目标是精确(而不是可读性)。
  • @Stephen C - 实际上,它来自 JavaSE 教程(由其他人链接)。在 JLS 中可能有类似的措辞,但我找不到相关部分。我在第 11 章(例外)、第 14 章(语句)或第 15 章(表达式)中已经预料到了这一点,但看不到任何明确提及中断的内容。我当然有兴趣看到。
  • @GaryF - 我明白了。实际上,JLS 谈到了语句的“正常”和“突然”终止,并且有一节(14.1)定义了术语。然后,finally 的行为被指定为正常终止和突然终止。
【解决方案2】:

是的。

documentation

finally 块 always 在什么时候执行 try 块退出。

例外:

注意:如果 JVM 在尝试时退出 或捕获代码正在执行,然后 finally 块可能不会执行。 同样,如果线程执行 try 或 catch 代码被中断或 被杀了,finally块可能不会 即使应用程序作为 整体继续。

【讨论】:

    【解决方案3】:

    最后,块总是执行。

    public class ExceptionTest {
    
    public static void someFunction(String input) throws Exception {
        try {
            if( input.equals("ABC") ) {
                System.out.println("Matched");
            }
        } catch (Exception e) {
            throw new Exception(e);
        } finally {
            System.out.println("Input Is "+input+" Finally Executed!!!");
        }
    }
    
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            System.out.println("********* Test with VALUE ********* ");
            someFunction("ABC");
            System.out.println("\r\n********* Test with NULL  ********* ");
            someFunction(null);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    

    }

    【讨论】:

      【解决方案4】:

      无论你的情况如何,最终总是被执行,即

      • try-catch-finally 块
      • 抛出

      对于未经检查的异常,java不强制,错误处理。 这就是原因,如果 finally 块中发生未经检查的异常并且没有对此进行处理,则在此点(发生错误的位置)以下编写的代码将不会被执行。

      所以我建议始终处理所有异常,无论是选中还是未选中。 这样,您可以确保 finally 中的代码块也被执行,无论是否也发生未经检查的异常。您在子巢中占有一席之地,然后终于阻止您完成必要的工作。

      【讨论】:

        【解决方案5】:

        The finally block always executes when the try block exits.unless 您的尝试或捕获中有 System.exit(0)。

        【讨论】:

          【解决方案6】:

          是的。 finally 块始终执行,除非您调用 System.exit() 因为它会停止 Java VM。

          【讨论】:

          • 在 System.exit() 之后仍会调用关闭钩子,但现有的非系统线程全部停止。
          猜你喜欢
          • 2010-10-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-02
          • 2012-08-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多