考虑到这段代码,我能绝对确定finally块总是执行的吗,不管something()是什么?

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("I don't know if this will get printed out");
}

当前回答

下面是凯文的回答。重要的是要知道,要返回的表达式在finally之前求值,即使在finally之后返回。

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int printX() {
    System.out.println("X");
    return 0;
}

public static int test() {
    try {
        return printX();
    }
    finally {
        System.out.println("finally trumps return... sort of");
        return 42;
    }
}

输出:

X
finally trumps return... sort of
42

其他回答

是的,finally将在执行try或catch代码块后调用。

唯一不会被调用的时间是:

如果调用System.exit()如果调用Runtime.getRuntime().hart(exitStatus)如果JVM首先崩溃如果JVM到达try或catch块中的无限循环(或其他一些不可中断、不终止的语句)如果操作系统强制终止JVM进程;例如,在UNIX上,kill-9<pid>如果主机系统失效;例如,电源故障、硬件错误、操作系统死机等如果finally块将由守护程序线程执行,并且所有其他非守护程序线程在finally调用之前退出

我很晚才回答,但我很惊讶没有人提到Java调试器选项来删除堆栈帧。我是IntelliJ中此功能的重度用户。(我确信Eclipse和NetBeans支持相同的功能。)

如果我从后面跟着finally块的try或catch块中删除堆栈帧,IDE将提示我:“我要执行finally块吗?”显然,这是一个人工运行时环境——调试器!

为了回答您的问题,我想说,只有在连接调试器时忽略,并且(就像其他人所说的)method something()不(a)通过JNI调用Java方法System.exit(int)或(b)C函数exit(int/abort(),或(C)对自身执行类似于调用kill-9$PID(!)的疯狂操作时,才能保证它运行。

如果抛出异常,则最终运行。如果未引发异常,则最终运行。如果捕获到异常,则最终运行。如果未捕获异常,则最终运行。

只有当JVM退出时,它才不会运行。

是的,会的。唯一不会发生的情况是JVM退出或崩溃

试用间苯二酚示例

static class IamAutoCloseable implements AutoCloseable {
    private final String name;
    IamAutoCloseable(String name) {
        this.name = name;
    }
    public void close() {
        System.out.println(name);
    }
}

@Test
public void withResourceFinally() {
    try (IamAutoCloseable closeable1 = new IamAutoCloseable("closeable1");
         IamAutoCloseable closeable2 = new IamAutoCloseable("closeable2")) {
        System.out.println("try");
    } finally {
        System.out.println("finally");
    }
}

测试输出:

try
closeable2
closeable1
finally