考虑以下启用了空分析的Eclipse项目的部分内容:
用于Windows 64位的Eclipse Mars版本(4.5.0; 20150621-1200)
Oracle JDK 1.8.0_60
package-info.java
@org.eclipse.jdt.annotation.NonNullByDefault
package bar;
Foo.java
package bar;
public class Foo {
public static void main(String[] args) {
}
}
class Base<T> {
private final Class<T> type;
public Base(Class<T> type) {
this.type = type;
}
public Class<T> getType() {
return this.type;
}
}
class Derived extends Base<String> {
public Derived() {
super(String.class); // <-- Null type safety warning here
}
}
Null分析在Derived
中对超类ctor的调用中产生以下警告:
Null type safety (type annotations): The expression of type 'Class<String>' needs unchecked conversion to conform to '@NonNull Class<@NonNull String>'
避免此警告的正确方法是什么?
答案 0 :(得分:1)
您所看到的冲突是在类型参数之间......
@NonNull String
String
来自extends Base<String>
的{{1}}图片中出现了非空类型参数,该版本在@NonNullByDefault
制度下扩展为extends Base<@NonNull String>
。从这里开始渗透到超级构造函数,在类型参数替换后将其签名呈现为(@NonNull Class<@NonNull String>)
。相比之下,编译器将类文字看作具有类型@NonNull Class<String>
,这是不兼容的。
真正的解决方案将来自Bug 477719,特别参见评论3 f中的讨论。
目前(使用Eclipse Mars)您可能必须减少@NonNullByDefault
的影响,以便接受@NonNull Class<String>
。这可以通过类{@ 1}}之类的更具体的@NNBD声明来实现,就像这样
Derived
在这里,我们正在利用这一事实,@ NNBD可以根据其适用的位置进行微调。在此声明中,与无参数import static org.eclipse.jdt.annotation.DefaultLocation.*;
...
@NonNullByDefault({PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND})
class Derived extends Base<String> {
...
的区别在于省略了位置@NonNullByDefault
,这意味着TYPE_ARGUMENT
中的String
将不再像上面提到的那样受到影响。因此,超级构造函数将具有此签名:extends Base<String>
并且所有编译都没有警告。
通过将精细调整的@NNBD放在类(@NonNull Class<String>)
上,此变通办法的范围尽可能小。