【发布时间】:2016-01-15 17:26:29
【问题描述】:
我正在将项目的 java 代码库从 java7 迁移到 java8。在此过程中,我还将从 javax.annotation @Nullable、@NonNull 和 @ParametersAreNotNullByDefault 注释切换到 org.eclipse.jdt 注释,以便在 Eclipse 中进行空值分析(Mars 版本 4.5.0:Build id:20150621-1200)。 在这样做时,我偶然发现了一种我无法编译的情况(因为关于基于注释的空检查的严格 Eclipse 设置),因为我无法解释。我不是在寻找一种方法来编译我的代码,而是更多地了解错误发生的原因。
我在包中有以下类,在 package-info.java 中使用 @NonNullByDefault 指定默认非空值。
我有一个由抽象类实现的接口,该抽象类又由一个具体类扩展,如下所示:
public interface SimulationComponent {
<T extends SimulationComponent> List<T> getCorrectSimulationSubComponents();
List<? extends SimulationComponent> getErroneousSimulationSubComponents();
}
public abstract class AbstractSimulationComponent
implements SimulationComponent {
@Override
public List<SimulationComponent> getCorrectSimulationSubComponents() {
return Collections.emptyList();
}
@Override
public List<SimulationComponent> getErroneousSimulationSubComponents() {
return Collections.emptyList();
}
}
public class ConcreteSubSimComponent extends AbstractSimulationComponent {
public void doSomething() {
}
}
Eclipse 在 ConcreteSubSimComponent 中通知我以下问题:
The method @NonNull List<@NonNull SimulationComponent> getErroneousSimulationSubComponents() from
AbstractSimulationComponent cannot implement the corresponding method from SimulationComponent due
to incompatible nullness constraints
这个问题似乎是由getErroneousSimulationSubComponents() 中的泛型通配符引起的。这就是我如何指定导致我在迁移到 java8 时注意到问题的方法。
我发现只需将此方法签名替换为getCorrectSimulationSubComponents() 中显示的签名即可“轻松”解决问题。
我不明白为什么最后一个版本有效而以前的版本无效。
此外,这似乎只是具体子类中的问题。直接实现接口的具体类不会出现任何问题。
我正在使用 JavaSE-1.8 和一个示例项目,其中包含无法编译的代码,可以在 https://github.com/KrisC369/NullProblemIllustration 找到
【问题讨论】:
-
您尝试过更新的 Eclipse 版本吗?如果是因为 Eclipse 编译器中的错误,它可能已经修复了。我知道在 neon 和 mars.2 中修复了一些与 null 分析相关的错误。查看 eclipse bugzilla 中针对 jdt 核心提交的标记为 [null] 的错误。如果找不到适合您问题的解决方案,请提交错误
-
看来 mars.1 构建仍然存在错误,而我无法在 mars.2rc2 和 neon-M4 构建中重现它。周末提交了一个错误报告link,它似乎也符合我正在经历的行为,但它是在 JDT-Core 4.6.0 版本下提交的。
标签: java eclipse generics eclipse-jdt type-annotation