javaeclipsegenericseclipse-jdttype-annotation

Incompatible nullness constraints in java class hierarchy with generics


I am in the middle of migrating my java codebase for a project from java7 to java8. In the process I am also switching from the javax.annotation @Nullable, @NonNull and @ParametersAreNotNullByDefault annotations to the org.eclipse.jdt annotations for null-analysis in eclipse (Mars Release 4.5.0:Build id: 20150621-1200). In doing this, I stumbled upon a situation where I can't compile (because of strict eclipse settings with regard to annotation based null checking) because of something I can't explain. I am not looking to find a way to compile my code, but more to understand why the error is occurring.

I have the following classes in a package specifying default non nullness using @NonNullByDefault in a package-info.java.

I have an interface implemented by an abstract class which is in turn extended by a concrete class as follows:

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 notifies me of the following problem in ConcreteSubSimComponent:

The method @NonNull List<@NonNull SimulationComponent> getErroneousSimulationSubComponents() from 
 AbstractSimulationComponent cannot implement the corresponding method from SimulationComponent due 
 to incompatible nullness constraints

This problem seems to be caused by the generics wildcard in getErroneousSimulationSubComponents(). This is how I specified the method that resulted in me noticing the problem when migrating to java8. I figured out that I could 'easily' fix things by just replacing this method signature to the one shown in getCorrectSimulationSubComponents(). I don't see why this last version works and the previous version doesn't.

Also, this only seems to be a problem in the concrete subclass. A concrete class directly implementing the interface does not show any problems.

I am using JavaSE-1.8 and an example project with the code that does not compile, can be found at https://github.com/KrisC369/NullProblemIllustration


Solution

  • Apparantly, this bug has been resolved by the changes introduced to fix bug 436091 against JDT-core. This fix should be present in eclipse Mars.2 (4.5.2) and eclipse neon-M4 (4.6.0-M4).