javagenericsinheritancejava-8

How to return an implementation of a genericized subclass in Java


I have the following structure:

    class Base{}
    class Extension1 extends Base{}
    class Extension2 extends Base{}
    abstract class AbstractClazz<T extends Base>{}
    class Clazz1 extends AbstractClazz<Extension1>{}
    class Clazz2 extends AbstractClazz<Extension2>{}

    <T extends Base>  AbstractClazz<T> method(boolean returnClass1){
        if (returnClass1){
          return new Clazz1();
        }
        return new Class2();
    }

However, my compiler gives me an error stating "Cannot convert from Clazz1 to AbstractClazz". I'm not sure why this is happening. Clazz1 and Clazz2 meet the requirements of an instance of AbstractClazz<T extends Base>, as far as I understand, because Clazz1 and Clazz2 are implementations of AbstractClazz where the the generic type is a subclass of Base, which is what AbstractClazz<T extends Base> is expecting.

How do I fix this?

note: my code is written using Java 8.


Solution

  • <T extends Base>  AbstractClazz<T> method(boolean returnClass1){
    

    Type parameters like <T extends Base> are in many ways like boolean returnClass1: the caller picks them.

    For example, the caller can write

    class MyRandomExtensionOfBase extends Base{}
    
    AbstractClazz<MyRandomExtensionOfBase> thingy = Foo.<MyRandomExtensionOfBase>method(true);
    

    ...and that's supposed to work.

    That's not what you have. You have a function that returns AbstractClazz<? extends Base>, returning some AbstractClazz<T> for some T extends Base decided by the implementation of method.

    You must return that type for this to typecheck.