75

请参阅以下代码并解释输出行为。

public class MyFinalTest {

    public int doMethod(){
        try{
            throw new Exception();
        }
        catch(Exception ex){
            return 5;
        }
        finally{
            return 10;
        }
    }

    public static void main(String[] args) {

        MyFinalTest testEx = new MyFinalTest();
        int rVal = testEx.doMethod();
        System.out.println("The return Val : "+rVal);
    }

}

结果是返回 Val : 10。

Eclipse 显示警告:finally block does not complete normally.

catch 块中的 return 语句会发生什么?

4

8 回答 8

79

它被 中的那个覆盖finally,因为finally在其他所有内容之后执行。

这就是为什么,一条经验法则——永远不要从finally. 例如,Eclipse 显示该片段的警告:“finally 块未正常完成”

于 2011-04-18T10:52:10.467 回答
54

finally总是被执行(唯一的例外是System.exit())。你可以这样想这种行为:

  1. 抛出异常
  2. 异常被捕获并且返回值设置为 5
  3. finally 块被执行并且返回值设置为 10
  4. 函数返回
于 2011-04-18T10:53:24.110 回答
20

如果您还记得 VM 的低级布局,这是一个简单的问题。

  1. 返回值由 catch 代码放入堆栈。
  2. 之后,finally 代码被执行并覆盖堆栈上的值。
  3. 然后,该方法返回要由调用者使用的最新值 (10)。

如果不确定这样的事情,请回到您对底层系统的理解(最终进入汇编程序级别)。

有趣的旁注

于 2011-04-18T11:10:11.890 回答
5

在此处输入图像描述

finally 块总是被执行,除非并且直到 System.exit() 语句在 finally 块中是第一个。

因此,在上面的示例中,执行由 try 语句引发并在 catch 块中捕获。有值为5的 return 语句,因此在堆栈调用中,值5稍后在 finally 块执行时添加,最新的返回值在返回值时添加到堆栈顶部,堆栈根据堆栈行为“LAST IN FIRST OUT”返回最新值,所以它将返回值为10。

于 2017-05-20T12:36:21.787 回答
3

finally块总是被执行(如果匹配的 try 被执行了),所以在该方法返回 5 之前catch,它会执行该finally块并返回 10。

于 2011-04-18T10:53:29.653 回答
2

简而言之,我们可以说finally 块支配 return 语句,而不管trycatch块中是否存在 return 。

在那个用例中总是最终占主导地位。

public static int m1() {
    try {
        return 100;
    } 
    catch(Exception e)
    {
        return 101;
    }
    finally {
        return 102;
    }
}

输出 - 102

于 2020-01-27T18:20:41.080 回答
1

finally 块将始终执行(唯一的例外是它在它之前的任何地方遇到 System.exit()),所以在 finally 块返回之前,只需将 5 替换(覆盖)为 10

于 2020-01-31T06:41:54.940 回答
0

finally 部分将始终执行。例如,如果您有任何要发布或注销的东西,如果发生错误,则转到 catch 部分,否则最终将执行。

Session session //  opened some session 
try 
{
 // some error 
}
catch { log.error }
finally 
{ session.logout();}

它不应该用来返回任何东西。你可以在外面使用。

于 2014-01-15T08:02:57.513 回答