2016-08-18 73 views
0

我知道如果java发现一行代码,它确保控件永远不会到达,然后编译器报告无法访问的代码错误。
请考虑以下代码。无法访问的代码try-catch-finally

static int method1() { 

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

在上面的代码
try块通过返回1,但仍然行之后最后块(LINE-2起)的网络层可达保证退出。
。如果我评论catch块(LINE-1),LINE-2变得无法访问。

为什么会这样。情况1中编译器无法在try块中看到无条件返回。

+0

例外情况不保证发生。它可能发生(在这里你知道它不会发生),所以它没有任何错误。 – Kishore

回答

5

这是JLS 14.21相关部分:

一个try语句可以当且仅当以下两个正常完成为真:

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

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

在这种情况下,虽然你的try块不能正常完成,它有一个catch块可以完全正常。finally块也可以正常完成。

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

如果删除了catch块,则上述引用部分中的第一个项目符号不再为真 - 这表示try语句无法正常完成,并且其后面的语句无法访问。

1

编译器看到你有一个catchException并假设它可能发生(因为你告诉它它可以)。由于finallycatch之后是可到达的,所以它后面的代码也是如此(因为catch块不会终止该功能,finally也不会)。第二个注释掉catch,编译器知道它在任何情况下都不会超过最终值,从而导致错误。

2

A try block(well,with a catch)告诉编译器“这里可能会导致异常”。因此,编译器假定即使其中有return语句,try可能不会成功返回。

考虑到这个假设,有逻辑路径将达到catchfinally。并且由于这些都不会返回,所以相同的逻辑路径将完全结束整个try/catch/finally并导致其后的代码到达。基本上,编译器(以及其设计者)更喜欢简单的规则到复杂的规则。简单的规则更容易测试和支持,并且可以向后兼容未来的版本。因此,尽管对人类谁是更深入地分析逻辑,它是不可能达到该代码,编译器完全有可能。

+0

你打我吧:) – Kishore

+0

然后为什么它显示错误的第二种情况。 –

+0

在第二种情况下,您告诉编译器不存在发生异常的可能性并返回值。所以下面的代码是无法访问的。 – Kishore

1

你不需要想到try块中的return语句,而是想到try块本身。它看到try块,并要求catch在那里(可以有一个finally块)。如果你删除catch语句,try块不知道该怎么办,如果发生错误,所以它下面的东西将不会被达到(因此无法访问的代码错误)

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

当你有一个catch语句时,compile kinda会像 - I会尝试“代码在这里”,如果出现错误,我会捕获错误并执行“代码在这里”,并可选择最终执行“代码在这里”。然后我会像平常一样在块的下面执行。