Java EclipseNull分析为类文本发出null类型安全警告

Java EclipseNull分析为类文本发出null类型安全警告,java,eclipse,null,annotations,eclipse-jdt,Java,Eclipse,Null,Annotations,Eclipse Jdt,考虑启用了空分析的Eclipse项目的以下部分内容: 适用于64位Windows的Eclipse Mars版本(4.5.0;20150621-1200) Oracle JDK 1.8.0_60 package info.java @org.eclipse.jdt.annotation.NonNullByDefault package bar; package bar; public class Foo { public static void main(String[] args)

考虑启用了空分析的Eclipse项目的以下部分内容:

适用于64位Windows的Eclipse Mars版本(4.5.0;20150621-1200)
Oracle JDK 1.8.0_60

package info.java

@org.eclipse.jdt.annotation.NonNullByDefault
package bar;
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
    }
}
Foo.java

@org.eclipse.jdt.annotation.NonNullByDefault
package bar;
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
    }
}

避免此警告的正确方法是什么?

您看到的冲突是类型参数之间的冲突

  • 。。。所需类型的:
    @非空字符串
  • 。。。提供的类型:
    String
非null类型参数来自
extends Base
,在
@NonNullByDefault
的机制下,它被扩展为
extends Base
。从这里开始,它一直渗透到超级构造函数,在类型参数替换后将其签名呈现为
(@NonNull Class)
。相反,类文本被编译器视为具有类型
@NonNull class
,这是不兼容的

真正的解决方案将通过,具体见评论3 f中的讨论

目前(使用EclipseMars),您可能必须减少
@NonNullByDefault
的影响,以便接受
@nonNullClass
。这可以通过在类
Derived
之上的更具体的@NNBD声明来实现,如下所示

import static org.eclipse.jdt.annotation.DefaultLocation.*;
...
@NonNullByDefault({PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND})
class Derived extends Base<String> {
...
import static org.eclipse.jdt.annotation.DefaultLocation.*;
...
@NonNullByDefault({参数,返回类型,字段,类型绑定})
类派生的扩展基{
...
在这里,我们利用了一个事实,@NNBD可以根据其应用的位置进行微调。在这个声明中,无参数的
@NonNullByDefault
的区别在于省略了位置
TYPE_参数
,这意味着
扩展基
中的
String
将不再像因此,超级构造函数现在将具有以下签名:
(@NonNull Class)
,并且所有编译都没有警告


通过将经过微调的@NNBD放在类
派生的
上,此解决方法的范围尽可能小。

谢谢,Stephan。很抱歉在创建此问题之前没有返回并进行回顾。否则,我会看到您和Udo之间在创建错误af之后进行的额外讨论回答我之前的问题。有了这些信息,我就能够推断出你的解决方法,并为你节省了一些时间。:-)n.p.-希望这个答案将来对其他人也有帮助:)修复对于477719,假设
T.class
属于
class
类型有点奇怪。这会导致明显错误的语句,如
@NonNull String s=String.class.cast(null);
在没有警告的情况下通过。或者通常,它似乎假设任何方法使用
并返回
X
以返回非空值。只要系统库没有空注释,使用泛型库类不可避免地是一条崎岖不平的道路。请参阅
Class.cast()的javadoc:“@在强制转换后返回对象,如果obj为null,则返回null”。因此,该方法应具有签名
@Nullable T cast(@Nullable object)
,编译器将正确地分析您的代码段。幸运的是,外部注释允许您准确地进行分析。我同意将该类型参数硬编码为非空的选择有点随意,但我相信当时我们有充分的理由。不可能将此选项传递给用户。@StephanHerrmann我刚刚发现我遇到这个问题的项目还有另一个问题:当自定义注释具有
@Retention(RetentionPolicy.SOURCE)
时,即使所有涉及的类都在源代码中,它也不起作用。我可以接受它,但我认为Eclipse应该发出一个关于不受支持的
@Retention
的警告。