How do I get a class of the generic type inside of the super class constructor?
In other words I want a Class<T>
instance where T is the generic from my super class.
This would work in the code below for the ChildA
class where I define the generic class directly in the class itself, but I also need it to work when the child class is a generic class like in the example with GenericChildB
.
/**
* empty class
*/
private static class Foo{}
/**
* non generic class that extends from a generic class
*/
private static class ChildA extends GenericClass<Foo>{}
/**
* generic class that extends from a generic class
*/
private static class ClassChildB<T> extends GenericClass<T>{}
private abstract static class GenericClass<T> {
@SuppressWarnings("unchecked")
public GenericClass() {
Type type = getClass().getGenericSuperclass();
/**
* When constructed from ChildA:
* type = generics.Main$GenericClass<generics.Main$Foo>
* with other worlds the generic type
*
* But when constructed from GenericChildB:
* the generic type is just:
* type = generics.Main$GenericClass<T>
* and it throws an error when trying to cast his to an ParameterizedType
* because <T> is not an acctual class.
*
*/
System.out.println(type);
Class<T> classInstance = (Class<T>) ((ParameterizedType)type).getActualTypeArguments()[0];
//Goal is to get an Class<T> object inside of the constructor of GenericClass
System.out.println(classInstance);
}
}
public static void main(String[] args) {
//works :
GenericClass<Foo> genericClassA = new ChildA();
//does not work:
GenericClass<Foo> genericClassB = new GenericChildB<Foo>();
}
This happens because of type erasure in Java.
In the first case, you bind the non-generic class
ChildA
with a concrete implementation ofGenericClass
i.e.GenericClass<Foo>
at compile-time. So Java is able to use this information.In the second case, the binding between
GenericChildB
andFoo
only happens at run-time. Java is not able to use this information.Extend your example this way:
Because this class is non-generic, the binding happens at compile-time. You will be able to get type information again.
This may or may not be acceptable in your real scenario, but it's pretty much the only way to retain type information with Java type erasure.