无法访问的代码 - 尝试捕获 - 最终

时间:2016-08-18 16:40:12

标签: java exception return unreachable-code

我知道如果java找到一行代码,保证控件永远不会到达,那么编译器会报告无法访问的代码错误。
请考虑以下代码。

    static int method1() {

        try{ return 1; }
        catch(Exception e){ }  // LINE-1
        finally{ }
        System.out.println("abc");  //LINE-2
        return 2;
    }
}

在上面的代码中 1 尝试阻止保证退出1,但在最终阻止(LINE-2以后)之后仍然可以到达。 的 2 即可。如果我评论catch块(LINE-1),则LINE-2变得无法到达。

为什么会如此。编译器是否能够在case-1的try块中看到无条件返回。

4 个答案:

答案 0 :(得分:6)

这是JLS 14.21的相关部分:

  

如果满足以下两个条件,则try语句可以正常完成:

     
      
  • try块可以正常完成,或任何catch块都可以正常完成。

  •   
  • 如果try语句有finally块,则finally块可以正常完成。

  •   

在这种情况下,尽管您的try块无法正常完成,但它有一个可以正常完成的catch块。 finally块也可以正常完成。

try语句是可以访问的,并且可以正常完成,因此可以访问它之后的语句。

如果删除catch块,则上述引用部分中的第一个项目符号不再为真 - 这意味着try语句无法正常完成,其后的语句为不可到达的。

答案 1 :(得分:3)

try块(好吧,带有catch)告诉编译器“这里的内容可能会导致异常”。因此,编译器假定,即使其中有return个语句,try也可能无法成功返回。

鉴于这种假设,有一些逻辑路径可以到达catchfinally。由于这些都没有返回,因此相同的逻辑路径将完全结束整个try/catch/finally并导致在其之后到达代码。

基本上,编译器(以及其设计者)更喜欢简单的规则而不是复杂的规则。简单的规则更易于测试和支持,并且可以向后兼容未来的版本。因此,当对于正在更彻底地分析逻辑的人时,无法达到该代码,到编译器它完全有可能。

答案 2 :(得分:1)

编译器看到你有一个catchException并假设它可能发生(因为你告诉它可以)。由于finally之后可以访问catch,因此跟随它的代码也是如此(因为catch块不会终止函数,{{1}也不会})。第二个你注释掉finally,编译器知道它在任何条件下都不会超出最终,因此错误。

答案 3 :(得分:1)

您不需要考虑try块中的return语句,而是考虑try块本身。它看到try块并且需要catch在那里(可选地它可以有一个finally块)。如果删除catch语句,try块不知道如果发生错误该怎么办,所以不会到达它下面的任何内容(因此无法访问代码错误)

编译器认为“嗯,如果try块输出错误,这段代码会发生什么 - 下面的代码将不会执行,因为我没有被告知如何从该错误中恢复”

当你有一个catch语句时,编译有点想 - 我将尝试“CODE HERE”,如果出错,我将捕获错误并执行“CODE HERE”,并且我可以选择执行“CODE HERE”。然后我将像正常一样在块下面执行。