根据Java语言规范,无法到达的代码是一个错误。
引用自JLS:
其核心思想是从构造函数、方法、实例初始化程序、静态初始化程序的开头到包含该语句的本身之间必须存在一些可能的执行路径。分析考虑了语句的结构。除了while、do和for语句的条件表达式具有常量值true的特殊处理外,不考虑表达式的值在流程分析中。
这意味着if
块不被考虑在内,因为如果您通过if
语句的某个路径,则可以到达最终的打印语句。如果您更改代码如下:
public void foo() {
System.out.println("Hello");
if (true)
return;
else
return;
System.out.println("World!");
}
突然间它无法编译了,因为if语句中没有任何路径可以到达最后一行。
也就是说,符合Java规范的编译器不允许编译您的第一个代码片段。继续引用JLS:
例如,以下语句导致编译时错误:
while (false) { x=3; }
因为语句 x=3; 是无法到达的,但表面上类似的情况是:
if (false) { x=3; }
在编译时不会出现错误。优化编译器可能会意识到语句 x=3; 永远不会被执行,并选择省略生成的类文件中的该语句的代码,但是从技术上规定的意义上讲,语句 x=3; 不被视为“无法访问”。
Eclipse 给出的第二个警告与死代码有关,这是编译器生成的警告,根据 JLS 的规定并非“无法访问”,但在实际应用中却是如此。 这是Eclipse提供的额外lint风格检查。 这完全是可选的,通过使用Eclipse配置可以将其禁用,或将其转换为编译器错误而不是警告。
这个第二个块是一种“代码异味”,if (false)
块通常用于禁用调试目的的代码,留下它通常是意外的,因此会发出警告。
事实上,Eclipse还进行了更高级的测试,以确定 if 语句的可能值,以确定是否可能采取两条路径。例如,Eclipse 还会抱怨以下方法中的死代码:
public void foo() {
System.out.println("Hello");
boolean bool = Random.nextBoolean();
if (bool)
return;
if (bool || Random.nextBoolean())
System.out.println("World!");
}
第二个 if 语句将会产生无法访问的代码,因为它可以推断出在此时代码中 bool
变量只能是 false
。在这样一个短的代码片段中,两个 if 语句测试的内容显然相同,但如果代码中有10-15行的中间代码,那么这个差异可能就不再那么明显了。
因此,总结一下,两者之间的区别:一个被 JLS 禁止,而另一个则没有,但 Eclipse 将其检测作为向程序员提供的服务。
true
或false
的常量if
表达式作为一种开启或关闭代码的方式,例如调试或诊断代码,只需“翻转开关”。表达式if(true)
和if(DEBUGS)
属于这个类别。因此,无论是 Eclipse 还是任何其他 Java 编译器都不允许将它们视为错误。更重要的是,它明确要求如果这样的常量保护代码求值为false
,则应将其删除。 - Lawrence Dol