52

鉴于此代码:

String test() {
    try {
        return "1";
    } finally {
        return "2";
    }
}

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

在 Sun JVM 中,返回值为2,但我想确定,这不是 VM 相关的。

4

7 回答 7

58

是的,语言规范定义“2”是结果。如果 VM 以不同的方式执行此操作,则它不符合规范。

大多数编译器都会抱怨它。例如,Eclipse 会声称 return 块永远不会被执行,但这是错误的。

编写这样的代码是非常糟糕的做法,永远不要这样做:)

于 2010-02-22T09:38:48.413 回答
20

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

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

  • 如果 try 块的执行正常完成,则 [...]
  • 如果由于抛出值 V 而导致 try 块的执行突然完成,则 [...]
  • 如果 try 块的执行由于任何其他原因 R 突然完成,则执行 finally 块。然后有一个选择:
    • 如果 finally 块正常完成,[...]
    • 如果 finally 块由于原因 S 突然完成,则 try 语句由于原因 S 突然完成(并且原因 R 被丢弃)。
于 2010-02-22T10:25:20.427 回答
19

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

String test() {
    try {
        System.exit(0);
    } finally {
        return "2";
    }
}

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

因此,在您的示例中,返回值将是2.

于 2010-02-22T09:42:04.553 回答
7

是的,如果您从finally块中返回某些内容,它将替换您可能从tryorcatch块中返回的任何内容。

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

于 2010-02-22T09:52:07.840 回答
4

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

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

对于程序:

String test() {
        try {
            System.out.println("try");
            return "1";
        } finally {
            System.out.println("finally");
            return "2";
        }
    }

它转换为:

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";
    }

对于程序:使用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";
        }
    }

转换为:

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";
    }

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

于 2015-07-28T10:27:05.027 回答
1

您可以参考以下链接。我希望它能提供所有细节:

http://www.programmerinterview.com/index.php/java-questions/will-finally-run-after-return/

它说 finally 块将始终执行,即使 try 或 catch 块有返回语句。如果 finally 块也有 return 语句,那么这将覆盖 try 或 catch 块内的 return 语句,在这种情况下,try/catch 中抛出的任何异常都将被丢弃(不好的方法)。

于 2015-03-26T14:25:34.040 回答
0

上面的答案总结得很好,只是想在这里再补充一点。

private static int divide(int a , int b){
    try{
        return  a/b;
    }finally{
        System.out.println("In finally");
        return 1;
    }
}

如果我们传递 1,0 那么上面的方法将抑制它抛出的异常并返回结果。有人说过,上面的代码不应该在生产环境中使用。

  private static int divide(int a , int b){
        int result = 0;
        try{
            result =   a/b;
        }finally{
            System.out.println("In finally");
            result =  1;
        }

        return result;
    }

在 finally 块之后使用 return 语句将导致

Exception in thread "main" java.lang.ArithmeticException: / by zero
于 2019-01-14T18:44:16.853 回答