我更多地是从编译器理论的角度来问这个问题。为什么空指针分析没有考虑
Assert.notNull()
的影响?
Assert方法来自Spring,其实现为:
public static void notNull(Object object, String message) {
if (object == null) {
throw new IllegalArgumentException(message);
}
}
public static void notNull(Object object) {
notNull(object, "[Assertion failed] - this argument is required; it must not be null");
}
(这变得非常烦人,因为如果我使用这种断言实用程序,断言后第一次访问该变量会导致警告,这会阻止我实现无警告代码。)
如果我完全内联断言例程,对
a
的访问将不会被标记为空指针访问(在这种简单的情况下,它将成为死代码)。然而,静态方法不能被重写(除非没有字节码摆弄),那么编译器设计者的 POV 不进入方法调用内部进行空指针分析的理由是什么?
这只是性能问题还是有什么因素阻碍了这种做法的实现?或者使其与其他编译器检查一致(死代码分析也没有考虑该方法)?
为什么 Eclipse 空指针分析无法识别断言实用程序?
因为 Eclipse 空指针分析仅考虑它正在分析的方法的语句...而不是所调用的方法的语义。 (我当然不会期望/希望 Eclipse 编译器的分析代码将
Spring
断言方法视为特殊情况。)
这变得很烦人......
那就关闭空分析吧! (应该有一个 Eclipse 编译器首选项来执行此操作。)
或者更改您的代码,使该值不总是
null
。 或者删除取消引用 null
引用的(动态)无法访问的语句。
说实话,你的例子是如此做作,我无法想象有人会在真正的代码中做这样的事情。 没有任何“修复”不会改变代码的含义。 我想您的真实代码并非如此......
仔细想想,这里的问题大致相当于Java中检测未初始化变量和不可达语句的问题。 Eclipse 采用与 Java/JLS 相同的解决方案。
至于 Eclipse 应该 使用最先进的非本地分析代码的想法……我不同意。 它会使 Eclipse 的交互式编译慢得像糖浆一样。
不执行此操作还有其他原因,包括:
这当然更多的是讨论而不是问题。
您编译时使用的 jar 不一定是您运行时使用的 jar。特别是 Assert 将成为在生产环境中进行不同实现的候选者。
空指针错误比死代码错误更好(此处)。
eclipse编译器在后台持续编译。因此,由于情报的代价是速度损失,因此这种检查可能更适合像
findbugs