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 上,此解决方法的范围尽可能小。