How can I resolve this situation with Java Generics?

I have the following class hierarchy:

public abstract class MyParentObject {}
public abstract class MyObject<T> extends MyParentObject {}

public abstract class MyParentContainer<T extends MyParentObject> {
    private Class<T> valueType;
    protected MyParentContainer(Class<T> valueType) {
        this.valueType = valueType;
    }
}
public abstract class MyObjectContainer<T extends MyObject<?>> extends MyParentContainer<T> {
    protected MyObjectContainer(Class<T> valueType) {
        super(valueType);
    }
}

This works fine so far. There are several subclasses of MyObject and several container classes having some of those subclasses as valueType, e.g.

public class IntObject extends MyObject<Integer> {}
public class IntContainer extends MyObjectContainer<IntObject> {
    public IntContainer() {
        super(IntObject.class);
    }
}

Now I need to implement a container though that works with a mixed set of subclasses of MyObject.

public class AllObjectContainer extends MyObjectContainer<MyObject<?>> {
    public AllObjectContainer() {
        super(MyObject.class); // compile error here
    }
}

This does not compile, because "The constructor MyObjectContainer<MyObject>(Class) is undefined". Casting `MyObject.class` to `Class>` is not possible.

To solve this, I could use raw types:

  1. Change public class AllObjectContainer extends MyObjectContainer<MyObject<?>> to public class AllObjectContainer extends MyObjectContainer<MyObject>

This has consequences though because of type erasure, so I do not like this solution.

Alternatively I could enable casting by

  1. Change protected MyObjectContainer(Class<T> valueType) { to protected MyObjectContainer(Class<? extends T> valueType) { (add ? extends)
  2. Change super(MyObject.class) to super((Class<? extends MyObject<?>>) MyObject.class)

This method works, but the cast is marked as unchecked and changing the MyMiddleContainer-Constructor has potential side effects on other classes that extend it.

Are there any better solutions?

1 answer

  • answered 2020-11-24 13:16 Tom Hawtin - tackline

    So, MyClass.class is of type Class<MyClass> not Class<MyClass<?>>.

    This is really a question about reflection.

    The usual good solution to the problem of reflection is not to use reflection.

    I suggest removing the use of Class and replace with an interface of the operations you want. You can then, if you wish, place reflection nastiness within a particular implementation of that interface.