多个返回语句,无编译器错误

这是一个面试问题:

public class Demo {

    public static void main(String[] args) {
        System.out.println(foo());
    }

    static String foo() {
        try {
            return "try ...";
        } catch (Exception e) {
            return "catch ...";
        } finally {
            return "finally ..."; //got as result
        }
    }
}

我的问题是为什么没有编译时错误。当我在我的块中有 return 语句时,它必然会从 返回而不是和块。我试图用选项编译此代码,它给出了警告。finallyfinallytrycatch-Xlint

warning: [finally] finally clause cannot complete normally

答案 1

它不会给出编译错误,因为它是 Java 语言规范所允许的。但是,它会给出一条警告消息,因为在块中包含语句通常是一个坏主意。returnfinally

在您的示例中发生的情况如下。执行块中的语句。但是,必须始终执行该块,以便在块完成后执行该块。此处发生的语句将覆盖上一个语句的结果,因此该方法将返回第二个结果。returntryfinallycatchreturnreturn

同样,块通常不应引发异常。这就是为什么警告说块应该正常完成,也就是说,没有或引发异常。finallyfinallyreturn


答案 2

这在 Java 语言规范中进行了描述:

第14.17号——17美元

子句的突然完成可能会中断由语句发起的控制权转移。finallyreturn

14.20.2

如果块的执行正常完成,则执行块,然后有一个选择:tryfinally

  • 如果块正常完成,则语句正常完成。finallytry
  • 如果块由于原因 S 而突然完成,则语句由于原因 S 而突然完成。finallytry

如果块的执行由于任何其他原因R突然完成,则执行该块,然后有一个选择:tryfinally

  • 如果块正常完成,则语句由于原因 R 而突然完成。finallytry
  • 如果最终的块由于原因 S 而突然完成,则 try 语句由于原因 S 而突然完成(并且原因 R 被丢弃)。