浏览我的一个队友编写的一些旧代码,我发现了这个非常奇怪的代码:
if (...) {
// some code
} else if (this == null) {
System.out.println("I expected this to be dead code!");
}
很奇怪不是吗。AFAIK,this == null
条件永远无法true
,这对编译器来说应该是显而易见的,因为它知道this
的含义,并且null
两者。但令我惊讶的是,这并没有被标记为死代码。
我在Eclipse和命令行中都尝试了这段代码。我运行以下命令来启用所有警告:
javac -Xlint:all MyClass.java
它仍然没有给出任何警告。
相反,如果我将else if
块更改为:
else if (false) {
System.out.println("As expected, this is dead code");
}
正如我所料,里面的语句被标记为死代码。
那么为什么会有这种行为呢?这只会让我认为可能存在某些条件,实际上可以null
this
。是吗?
JLS 对无法访问的代码进行了定义:
分析考虑了语句的结构。除了对 while、do 的特殊处理以及条件表达式具有常量值 true 的语句外,流分析中不考虑表达式的值。
因此,这不被视为"无法访问"。
另请参阅有关无法访问的代码错误和死代码警告的讨论。
编译器在检测隐式总是错误的条件方面似乎参差不齐,即使它被 JLS 暗示或陈述/明显是假的,那么它可能不会注意到这一事实。当简单地列出一组要检查的"明显条件"时,is-null 检查并不那么容易捕获,因此它可能被忽略了。
Rice 定理意味着检查 Java 表达式的计算结果是否为 false
是不可判定的。 也就是说,理论上不可能确定某些任意代码是否死亡。
由于Java编译器无法检测到所有死代码,因此开发人员确定了一组他们可以检测到的非常具体的死代码实例。