从 finally 块返回一个值

Returning a value from a finally block

我在一个java认证网站上找到了这段代码

   public class Test1{
        public static void main(String args[]){
            System.out.println(method());
        }
        public static int method(){
           try{
              return 1;
           }
           catch(Exception e){
              return 2;
           }
           finally{
              return 3;
           }
        }
    }

所以这段代码的输出显示为3。 这怎么可能……因为它在 try 块本身中返回 1? 代码永远不会到达 finally 对吧??

代码永远不会到达 finally 对吗? 不会,如果有finally块控制会在try or/and catch

后转到finally

因为无论如何finally都会执行。除了 Mike Kobit 所说 System.exit

感谢 Jason C,来自 JLS 14.17. The return Statement

It can be seen, then, that a return statement always completes abruptly.

The preceding descriptions say "attempts to transfer control" rather than just "transfers control" because if there are any try statements (§14.20) within the method or constructor whose try blocks or catch clauses contain the return statement, then any finally clauses of those try statements will be executed, in order, innermost to outermost, before control is transferred to the invoker of the method or constructor. Abrupt completion of a finally clause can disrupt the transfer of control initiated by a return statement.

来自JLS 14.20.2. Execution of try-finally and try-catch-finally

If execution of the try block completes normally, then the finally block is executed, and then there is a choice:

  1. If the finally block completes normally, then the try statement completes normally.
  2. If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S.

所以在你的代码中尝试 returns 1,然后控制最终转到 returns 3。所以 return 函数的值将是 3。

因为如果我们考虑优先级 finallytrycatch 多,要弄清楚即使没有捕获到异常,finally 也会执行并在这里当一个方法被假设为 return 单个输出 int 值时,它在一个方法内部工作,那么显然它总是 return 来自 finally.[=15= 的值]

有道理吗?

Finally 块将始终在 return 语句执行之前执行。 (有一些异常,比如 JVM 本身崩溃或 system.exit() 被调用)

原因如下:

我们通常使用 finally 来释放我们的资源或进行清理。现在,如果开发人员不小心在 try 块中写入 return 语句,那么逻辑上 finally 将永远不会被执行。为了克服这个问题,JVM 自己处理这种情况并在 return 从 try 块开始之前执行 finally 块。

记住 finally 块总是在 try 块退出时执行。以上解释的场景也适用于return、继续或中断

正如 Sumit Singh 在他的回答中提到的,发生这种情况是因为 return 导致方法突然结束。

当您在 try-catch-finally 块中抛出新异常时,您可以观察到相同的行为,因为 throw 也是 abrupt

见以下代码:

public class FinallyTest {
    public static void main(String[] args) {
        abrupt();
    }

    @SuppressWarnings("finally")
    public static void abrupt() {
        try {
            throw new IllegalArgumentException("In Try");
        }
        catch(Exception x) {
            throw new IllegalArgumentException("In Catch");
        }
        finally {
            throw new NullPointerException("In Finally");
        }
    }
}

当运行代码时,控制台显示

Exception in thread "main" java.lang.NullPointerException: In Finally
at FinallyTest.abrupt(FinallyTest.java:15)
at FinallyTest.main(FinallyTest.java:3)

即使你在 try 块中抛出一个新的 IllegalArgumentException,也只会抛出 finally 块中的 NullPointerException,因为这个块突然结束了。