多个返回语句没有编译器错误

64 java compiler-errors return try-catch try-catch-finally

这是一个采访问题:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么没有编译时错误.当我在finally块中有return语句时,它必然会从而finally不是trycatch块返回.我尝试使用-Xlint选项编译此代码,它会发出警告.

warning: [finally] finally clause cannot complete normally
Run Code Online (Sandbox Code Playgroud)

Hoo*_*pje 77

它不会产生编译错误,因为Java语言规范允许它.但是,它会发出警告消息,因为returnfinally块中包含一个语句通常是个坏主意.

您的示例中发生的情况如下.块中的return语句try被执行.但是,finally必须始终执行该块,以便在catch块完成后执行该块.在return那里发生的语句会覆盖前一个return语句的结果,因此该方法返回第二个结果.

类似地,finally块通常不应该抛出异常.这就是为什么警告说finally块应该正常完成,也就是说,没有return或抛出异常.

  • 很好的答案!好的解释和明确的例子.不仅仅是引用规格 (3认同)

Dra*_*vic 39

这在Java语言规范中描述:

§14.17

突然完成一个finally条款可以破坏由return声明发起的控制权转移.

§14.20.2

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

  • 如果finally块正常完成,则try语句正常完成.
  • 如果finally块因原因S突然完成,则try语句突然完成,原因是S.

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

  • 如果finally块正常完成,则try语句突然完成,原因是R.
  • 如果finally块因原因S而突然完成,则try语句突然完成,原因为S(并且原因R被丢弃).


Aak*_*ash 10

没有编译时错误,因为只有1和1的return语句实际上会将控件返回给调用代码.

正如@Hoopje所解释的那样,return在他们内部trycatch将首先执行,他们各自的返回声明也将执行.但就在将控制权返回给调用代码之前,它将执行该finally块.现在,这block也是return一些东西,所以这个回归会覆盖前一个回归.

  • 事实并非如此.将执行两个return语句,但第二个将覆盖第一个语句. (2认同)

Las*_*ama 8

很棒的问题..根据我的知识,如果你已经将finally块添加到你的代码中,那么try和catch块的return语句将被转移到finally.这是它的工作方式.

所以在这种情况下,所有代码行都在执行,您可以尝试调试.我在代码下面尝试了所有三个块.

public class Main {

    public static void main(String[] args) {
        System.out.println(foo());
    }
    static String foo() {
        try {
            throw new Exception();
        } catch (Exception e) {
            return "catch ...";
        } finally {
            return "finally ..."; //got as result
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以从下面的链接中获取想法. 多次返回:哪一个设置最终返回值?


Roe*_*erg 8

它与此基本相同:

public boolean someMethod(){
        if(1 == 1){
            return true;
        }
        return false;
}
Run Code Online (Sandbox Code Playgroud)

它不会给出编译错误,但它会发出警告.只有在没有执行返回语句的情况下,编译器才会给出错误.


tha*_*uja 5

您的代码工作正常,因为在try,catch和finally块中只有一个return语句.如果您尝试在try,catch或finally块之一中写入两个返回语句,表示存在无法返回的返回语句,则会发生编译错误.


Tej*_*sad 5

(简短答案- 阅读答案的粗体和斜体部分

按照Java 8文档的执行流程。它为您提供详细信息。您可以根据以下内容推断return语句的执行。

通过首先执行try块来执行带有finally块的try语句。

然后有一个选择:

•如果try块的执行正常完成,则执行finally块,然后可以选择:

–如果finally块正常完成,则try语句正常完成。

–如果由于原因S突然完成了finally块,则由于原因S导致try语句突然完成。

•如果由于抛出值V而导致try块的执行突然完成,则可以选择:

–如果V的运行时类型与try语句的任何catch子句的可捕获异常类的赋值兼容,则选择第一个(最左侧)的此类catch子句。将值V分配给所选catch子句的参数,并执行该catch子句的Block。

然后有一个选择:

›如果catch块正常完成,则执行finally块。然后有一个选择:

»如果finally块正常完成,则try语句正常完成。

»如果finally块由于某种原因突然完成,则try语句由于相同的原因突然完成。

如果catch块由于原因R突然完成,则执行finally块。然后有一个选择:

»如果finally块正常完成,则try语句由于原因R突然完成。

» 如果final块由于原因S突然完成,则try语句由于原因S突然完成(并且原因R被丢弃)。

–如果V的运行时类型与try语句的任何catch子句的可捕获异常类的赋值不兼容,则将执行finally块。

然后有一个选择:

›如果finally块正常完成,则try语句由于抛出值V而突然完成。

›如果finally块由于原因S突然完成,则try语句由于原因S突然完成(并且丢弃了值V,并且将其抛弃了)。

•如果由于任何其他原因R导致try块的执行突然完成,则执行finally块,然后可以选择:

–如果finally块正常完成,则try语句由于原因R突然完成。

–如果final块由于原因S突然完成,则try语句由于原因S突然完成(并且原因R被丢弃)。

该链接中的解释很清楚-javaDoc