Search code examples
javagenericsbounded-types

Return bounded type is incompatible with a type that matches the bound


I’m pretty sure something like this has been asked but I can’t really find the exact wording, so here it goes.

If I have these three classes:

package boundedtypetest;

public class Factory {
    private class ClassA {}

    private class ClassB extends ClassA {}

    public <T extends ClassA> T create() {
        return new ClassB();
    }
}

Why does the Java compiler say that T and ClassB are incompatible in the create method?


Solution

  • You've created a generic method by declaring T as a type parameter with an upper bound. With generic methods, you must be aware that the caller can decide what T is by passing an explicit type argument to your method.

    class ClassC extends ClassA {}
    
    ClassC c = new Factory().<ClassC>create();
    

    There is no guarantee that the type parameter chosen by the caller, explicitly or implicitly, will match the type of what is returned, and you're returning a ClassB. The compiler cannot guarantee type safety here so this is disallowed.

    If you don't need the generics, remove the type parameter off the method and declare create to return a ClassB, ClassA, or Object.

    If you need the generics, then you must take a parameter of type Class<T> and create an instance with it to satisfy the compiler.

    public <T extends ClassA> T create(Class<T> clazz) throws ReflectionRelatedExceptions 
    {
        return clazz.getConstructor().newInstance();
    }