即使抛出新的Exception,finally块也会运行吗?


142

someVar即使执行catch块并抛出第二个Exception,也会在此代码中进行设置?

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

2
因为在某些情况下行为不符合预期,如@GaryF
jax

1
值得注意的是,如果最终块抛出异常或返回,则可能无法按预期执行。
彼得·劳瑞

Answers:


184

是的,finally块始终运行...除非以下情况:

  • 运行try-catch-finally块的线程被杀死或中断
  • 你用 System.exit(0);
  • 基础虚拟机以其他方式被破坏
  • 基础硬件在某种程度上无法使用

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

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


4
在这里,“运行try-catch-finally块的线程被中断”是什么意思?也许该文档的措辞不佳,但是Thread.interrupt()不会导致finally块被跳过,无论是从try还是catch块抛出。这是否使用“中断”来表示更暴力的内容,例如Thread.stop()?
乔·科尔尼

@Joe:是的,我认为此处的文档措辞有点差,这意味着该线程的活动通常会中断。
GaryF

@GaryF-我想您是从JLS引述的。JLS的措词有时会有些奇怪,但是您通常会发现奇怪术语的含义在文档的其他位置已明确定义。JLS是一个规范,其主要目标是精度(而非可读性)。
Stephen C

1
@Stephen C-实际上,它来自JavaSE教程(已由其他人链接)。JLS中的措词可能与此类似,但我找不到相关的部分。我本来希望在第11章(异常),第14章(声明)或第15章(表达式)中看到此信息,但是看不到任何明确涉及中断的内容。我当然会对看到这个感兴趣。
GaryF

1
@GaryF-我明白了。实际上,JLS讨论的是语句的“正常”和“突然”终止,并且有一节(14.1)定义了术语。finally然后根据正常终止和突然终止来指定的行为。
Stephen C

10

是。

请参阅文档

try块退出时,finally块始终执行。

例外情况:

注意:如果在执行try或catch代码时JVM退出,则finally块可能不会执行。同样,如果执行try或catch代码的线程被中断或杀死,即使整个应用程序继续运行,finally块也可能不会执行。


2

最后,块始终执行。

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();
    }
}

}

Java尝试捕获最终阻止并抛出


2

无论您的情况如何,Finally总是执行

  • try-catch-finally块
  • 抛出

对于未经检查的异常,java不强制执行错误处理。这就是原因,如果在finally块中发生未经检查的异常,则对此不做任何处理,那么将不执行在此点以下发生的代码(发生错误的位置)。

因此,我建议始终处理所有被检查或未检查的异常。这样,无论是否发生未经检查的异常,您都可以确保也最终执行了代码块。您在子巢捕获中占有一席之地,而在“ 最后一块”中完成您的必要工作。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.