我知道如果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块中看到无条件返回。
答案 0 :(得分:6)
这是JLS 14.21的相关部分:
如果满足以下两个条件,则
try
语句可以正常完成:
try
块可以正常完成,或任何catch
块都可以正常完成。如果
try
语句有finally
块,则finally
块可以正常完成。
在这种情况下,尽管您的try块无法正常完成,但它有一个可以正常完成的catch块。 finally块也可以正常完成。
try
语句是可以访问的,并且可以正常完成,因此可以访问它之后的语句。
如果删除catch
块,则上述引用部分中的第一个项目符号不再为真 - 这意味着try
语句无法正常完成,其后的语句为不可到达的。
答案 1 :(得分:3)
try
块(好吧,带有catch
的)告诉编译器“这里的内容可能会导致异常”。因此,编译器假定,即使其中有return
个语句,try
块也可能无法成功返回。
鉴于这种假设,有一些逻辑路径可以到达catch
和finally
。由于这些都没有返回,因此相同的逻辑路径将完全结束整个try/catch/finally
并导致在其之后到达代码。
基本上,编译器(以及其设计者)更喜欢简单的规则而不是复杂的规则。简单的规则更易于测试和支持,并且可以向后兼容未来的版本。因此,当对于正在更彻底地分析逻辑的人时,无法达到该代码,到编译器它完全有可能。
答案 2 :(得分:1)
编译器看到你有一个catch
块Exception
并假设它可能发生(因为你告诉它可以)。由于finally
之后可以访问catch
,因此跟随它的代码也是如此(因为catch
块不会终止函数,{{1}也不会})。第二个你注释掉finally
,编译器知道它在任何条件下都不会超出最终,因此错误。
答案 3 :(得分:1)
您不需要考虑try块中的return语句,而是考虑try块本身。它看到try块并且需要catch在那里(可选地它可以有一个finally块)。如果删除catch语句,try块不知道如果发生错误该怎么办,所以不会到达它下面的任何内容(因此无法访问代码错误)
编译器认为“嗯,如果try块输出错误,这段代码会发生什么 - 下面的代码将不会执行,因为我没有被告知如何从该错误中恢复”
当你有一个catch语句时,编译有点想 - 我将尝试“CODE HERE”,如果出错,我将捕获错误并执行“CODE HERE”,并且我可以选择执行“CODE HERE”。然后我将像正常一样在块下面执行。