多次返回:哪一个设置最终返回值?

Dan*_*ski 46 java return finally

鉴于此代码:

String test() {
    try {
        return "1";
    } finally {
        return "2";
    }
}
Run Code Online (Sandbox Code Playgroud)

语言规范是否定义了调用的返回值test()?换句话说:每个JVM中它总是一样的吗?

在Sun JVM中,返回值是2,但我想确定,这不依赖于VM.

ska*_*man 48

是的,语言规范定义结果为"2".如果VM以不同方式执行,则它不符合规范.

大多数编译器会抱怨它.例如,Eclipse将声称永远不会执行返回块,但这是错误的.

编写这样的代码真是太糟糕了,不要这样做:)


pol*_*nts 20

是的,Java语言规范在这个问题上非常明确(14.20.2):

通过首先执行try块来执行具有finally块的try语句.然后有一个选择:

  • 如果try块的执行正常完成,[...]
  • 如果由于抛出值V而突然完成try块的执行,[...]
  • 如果try块的执行由于任何其他原因R突然完成,则执行finally块.然后有一个选择:
    • 如果finally块正常完成,[...]
    • 如果finally块由于原因S而突然完成,则try语句突然完成,原因S(并且原因R被丢弃).


Rom*_*las 17

除以下示例外,将始终执行finally块:

String test() {
    try {
        System.exit(0);
    } finally {
        return "2";
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,JVM将停止,而不执行finally块.

所以在你的例子中,返回值将是2.


Esk*_*ola 7

是的,如果您从finally块中返回一些内容,它将替换您从块trycatch块中返回的任何内容.

例外情况也是如此.如果你在finally块中抛出一些东西,该异常将替换tryor catch块中抛出的任何异常.所以要小心不要在finally块中扔东西,因为它可能隐藏失败的原始原因.


rhi*_*itz 5

读取程序的ByteCode后,代码如下:

finally 块语句内联在try 块的return 语句之前,因此finally 块的return 语句首先执行,而原始return 语句永远不会执行。

对于程序:

String test() {
        try {
            System.out.println("try");
            return "1";
        } finally {
            System.out.println("finally");
            return "2";
        }
    }
Run Code Online (Sandbox Code Playgroud)

它转换为:

String test()
    {
        System.out.println("try");
        String s = "1"; //temporary variable 
        System.out.println("finally");
        return "2";
        Exception exception;
        exception;
        System.out.println("finally");
        return "2";
    }
Run Code Online (Sandbox Code Playgroud)

对于程序:带有 catch 块:

String test() {

        try {
            System.out.println("try");
            return "1";
        } catch (RuntimeException e) {
            System.out.println("catch");
            return "2";
        } finally {
            System.out.println("finally");
            return "3";
        }
    }
Run Code Online (Sandbox Code Playgroud)

转换为:

String test()
    {
        System.out.println("try");
        String s = "1";
        System.out.println("finally");
        return "3";
        RuntimeException e;
        e;
        System.out.println("catch");
        String s1 = "2";
        System.out.println("finally");
        return "3";
        Exception exception;
        exception;
        System.out.println("finally");
        return "3";
    }
Run Code Online (Sandbox Code Playgroud)

注意:使用 JDK 1.7 编译并使用 Cavaj 反编译。