我正在使用Java 8尝试Checker Framework的Nullness检查程序。当我在以下代码上运行检查程序时:
import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
class A {
public void f() {}
}
public class Foo {
private Map<A,Integer> map = new HashMap<>();
private @Nullable A x;
public void setX(@Nullable A x) {
this.x = x;
}
public void call() {
if (x != null) {
map.put(x, 0);
x.f();
}
}
}
检查器在x.f();
上发出警告:取消引用可能的空引用x。当然,这是有道理的。 Checker Framework不知道map.put
做了什么。地图对象可能已引用this
,然后在其上调用setX(null)
。
现在我的问题如下。有没有办法告诉Checker Framework一个方法不会修改除了它所调用的对象之外的任何对象?由于map.put
没有调用setX
方法,因此x
的值不会改变。
要摆脱警告,我可以将调用方法更改为:
public void call() {
A y = x;
if (y != null) {
map.put(y, 0);
y.f();
}
}
现在没有警告。这也是有道理的:无法从外部访问局部变量。但我不想引入这个局部变量,其唯一目的是消除警告。
或者,我可以通过x
注释字段@MonotonicNonNull
。但在我的实际用例中,我希望保持将字段设置为null的可能性。
提前致谢!
答案 0 :(得分:1)
你的问题已经提供了几种抑制警告的好方法,所以你清楚地知道你在做什么。
但是,你想要一个更好的方法。您想知道如何使Checker Framework从不发出警告。你的关键问题是:
有没有办法告诉Checker Framework一个方法不会修改除被调用对象之外的任何对象?
不幸的是,Checker Framework目前没有此功能。 Manual section 21.4.3, "Side effects, determinism, purity, and flow-sensitive analysis", 讨论了Checker Framework如何表明纯度或无副作用。 @SideEffectFree和@Pure注释目前是全有或全无。
您对部分纯度注释的建议会很有用:它会使Checker Framework更具表现力,并且可以减少抑制警告的需要,这是目前所需要的。 (另一方面,用户学习也是另一回事;总是存在表达性 - 复杂性权衡。)我建议你向Checker Framework开发人员提出这个功能。