为什么在try catch finally中,返回值总是finally块的返回值?

4

在我的 catch 块中,return A 代码会发生什么?

public class TryCatchFinallyTest {

    @Test
    public void test_FinallyInvocation()
    {
        String returnString = this.returnString();
        assertEquals("B", returnString);
    }

    String returnString()
    {
        try
        {
            throw new RuntimeException("");
        }
        catch (RuntimeException bogus)
        {
            System.out.println("A");
            return "A";
        }
        finally
        {
            System.out.println("B");
            return "B";
        }
    }
}

这里已经有很多答案了。我找到了JLS中最相关的部分:http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.2。它明确指出,如果catch块成功完成,则执行finally块。在运行了一个示例并阅读了该部分之后,我认为在这种情况下,catch块的返回语句将被丢弃。 - pseudoramble
当然,你可能想要了解JVM实现显式执行的细节,而不是JVM应该表现出的行为。你能澄清一下你想要什么吗? - pseudoramble
5个回答

3

finally块会在方法中所有的return或exit之前执行。因此,当您执行

return "A";

它的执行方式如下:

System.out.println("B");//Finally block
return "B";//Finally block
return "A";//Return from exception catch

因此返回的是“B”,而不是“A”。

3
也许编译器优化了return "A";,也许没有并且"A"只是动态替换的。实际上这都无关紧要,因为你不应该有这段代码。
这是使用finally进行控制流的典型问题之一:你会失去一些指令,而另一个程序员可能无法看到“意图”(实际上只能是错误或恶意)。你可能已经注意到javac发出了警告:"finally块未正常完成"。 不要在finally子句中返回

0

finally块将始终被执行,而catch块仅在捕获异常时执行。


0

在执行return "A"之前,finally块将被调用,它将return "B",而你的return "A"将被跳过并永远不会被执行。这是因为finally块总是在方法的return语句之前执行,如果你从finally块中返回了某些内容,那么你的try/catch中的return语句将始终被跳过。

注意:从finally块中返回不是Java程序员的良好实践。如果你从finally块中返回某些内容,JAVA编译器也会显示警告信息“finally block does not complete normally”。


0

这个引用并没有明确表明被考虑的返回语句是 finally 块中的语句。 - Denys Séguret
看最后一行,finally块将在返回之前执行。因此,当找到return语句时,它将调用finally块,实际上是返回。 - greatmajestics

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接