Eclipse 空分析为 class 文字发出空类型安全警告
Eclipse null analysis issues null type safety warning for class literal
考虑启用空分析的 Eclipse 项目的以下部分内容:
Windows64 位
的 Eclipse Mars 版本 (4.5.0; 20150621-1200)
甲骨文 JDK1.8.0_60
包-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
}
}
空分析在 Derived
中调用超类 ctor 时产生以下警告:
Null type safety (type annotations): The expression of type 'Class<String>' needs unchecked conversion to conform to '@NonNull Class<@NonNull String>'
避免此警告的正确方法是什么?
您看到的冲突发生在类型参数之间...
- ...所需类型:
@NonNull String
- ... 提供的类型:
String
非空类型参数来自 extends Base<String>
,在 @NonNullByDefault
的规则下扩展到 extends Base<@NonNull String>
。从这里它一直渗透到超级构造函数,在类型参数替换后将其签名呈现为 (@NonNull Class<@NonNull String>)
。相比之下,class 文字被编译器视为具有类型 @NonNull Class<String>
,这是不兼容的。
真正的解决方案将来自 Bug 477719,具体请参阅评论 3 f.
中的讨论
暂时(使用 Eclipse Mars)您可能必须减少 @NonNullByDefault
的影响,以便 @NonNull Class<String>
被接受。这可以通过在 class Derived
之上的更具体的 @NNBD 声明来实现,例如
import static org.eclipse.jdt.annotation.DefaultLocation.*;
...
@NonNullByDefault({PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND})
class Derived extends Base<String> {
...
我们在这里利用了一个事实,@NNBD 可以根据它适用的位置进行微调。在这个声明中,与无参数 @NonNullByDefault
的区别在于省略了位置 TYPE_ARGUMENT
,这意味着 extends Base<String>
中的 String
将不再像上面提到的那样受到影响。因此,超级构造函数现在将具有此签名:(@NonNull Class<String>)
并且所有编译都没有警告。
通过将微调的@NNBD 放在 class Derived
上,此解决方法的范围尽可能小。
考虑启用空分析的 Eclipse 项目的以下部分内容:
Windows64 位
的 Eclipse Mars 版本 (4.5.0; 20150621-1200)
甲骨文 JDK1.8.0_60
包-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
}
}
空分析在 Derived
中调用超类 ctor 时产生以下警告:
Null type safety (type annotations): The expression of type 'Class<String>' needs unchecked conversion to conform to '@NonNull Class<@NonNull String>'
避免此警告的正确方法是什么?
您看到的冲突发生在类型参数之间...
- ...所需类型:
@NonNull String
- ... 提供的类型:
String
非空类型参数来自 extends Base<String>
,在 @NonNullByDefault
的规则下扩展到 extends Base<@NonNull String>
。从这里它一直渗透到超级构造函数,在类型参数替换后将其签名呈现为 (@NonNull Class<@NonNull String>)
。相比之下,class 文字被编译器视为具有类型 @NonNull Class<String>
,这是不兼容的。
真正的解决方案将来自 Bug 477719,具体请参阅评论 3 f.
中的讨论暂时(使用 Eclipse Mars)您可能必须减少 @NonNullByDefault
的影响,以便 @NonNull Class<String>
被接受。这可以通过在 class Derived
之上的更具体的 @NNBD 声明来实现,例如
import static org.eclipse.jdt.annotation.DefaultLocation.*;
...
@NonNullByDefault({PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND})
class Derived extends Base<String> {
...
我们在这里利用了一个事实,@NNBD 可以根据它适用的位置进行微调。在这个声明中,与无参数 @NonNullByDefault
的区别在于省略了位置 TYPE_ARGUMENT
,这意味着 extends Base<String>
中的 String
将不再像上面提到的那样受到影响。因此,超级构造函数现在将具有此签名:(@NonNull Class<String>)
并且所有编译都没有警告。
通过将微调的@NNBD 放在 class Derived
上,此解决方法的范围尽可能小。