可能重复:
Why is this code giving an “Unreachable Statement” error?
这似乎是一个非常简单的问题,我在一本书中找到了这个问题。如果有人帮我弄清楚为什么我会收到错误。
do {
System.out.print("inside do");
} while (false);
while (false) { // error
System.out.print("inside while");
}
System.out.print("outside");
我想,根据我的说法,输出应该是在dooutside内。但是,它显示编译器错误:无法访问的声明。然后,我试图找出,为什么,它显示编译错误:无法访问的声明* 。所以,我改变了上面这样的代码
boolean i = false;
do {
System.out.print("inside do");
} while (false);
while (i) { // ok
System.out.print("inside while");
}
System.out.print("outside");
现在,它显示预期的输出,即在dooutside内。所以,我的问题是 - 第一和第二种情况有什么不同? 另外,当我检查
if(false){
//something here
}
然后,上面的代码执行没有任何错误。
答案 0 :(得分:6)
前两个例子的主要区别在于,在第一种情况下,条件是常数,而在第二种情况下则不是。
例如,如果将boolean i = false;
更改为final boolean i = false;
,则会得到相同的编译错误,因为我现在是常量。
无法访问语句的规则在JLS 14.21中定义。特别是if
有一种特殊的处理方式,允许if(DEBUG)
结构DEBUG
可能是常数。
对于do / while
,内部语句将被执行一次,因此没有问题。
有关this related post中常量的更多详细信息。
答案 1 :(得分:5)
编译器为您提供无法访问的声明错误,因为无法使用
来访问System.out.print("inside while");
代码
while (false) { // error
System.out.print("inside while");
}
编译器知道while (false)
永远不会为真,并警告您(有错误)关于死代码。
相反,如果你在while
中放置一个变量,因为变量的性质是它们可以变化(变化),编译器的静态分析不能识别不可达码。 (即使在很多情况下,你或我可以看到它并说“代码永远不会被运行”;编译器的分析相当浅薄,这不是它的主要工作。你可以使用更强大的分析和代码覆盖工具使用。)
关于if (false)
,这是JLS has to say about it:
例如,以下语句导致编译时错误:
while (false) { x=3; }
因为声明
x=3
;无法到达;但表面上类似的情况:
if (false) { x=3; }
不会导致编译时错误。优化编译器可能会意识到语句
x=3;
将永远不会被执行,并且可能会选择从生成的类文件中省略该语句的代码,但语句x=3;
在该文件中不被视为“无法访问”这里指定的技术意义。这种不同处理的基本原理是允许程序员定义“标志变量”,例如:
static final boolean DEBUG = false;
然后编写如下代码:
if (DEBUG) { x=3; }
我们的想法是,应该可以将
DEBUG
的值从false更改为true或从true更改为false,然后正确编译代码而不对程序文本进行其他更改。