How does Guice\'s TypeLiteral overcome the Java generic types erasure procedure?
It works wonders but how is this accomplished?
The trick that is used here is that the signatures of generic super types are stored in subclasses and thus survive erasure.
If you create an anonymous subclass new TypeLiteral<List<String>>() {}
Guice can call getClass().getGenericSuperclass() on it and get a java.lang.reflect.ParameterizedType on which exists a method getActualTypeArguments() to get List<String>
as an instance of ParameterizedType
.
By a combination of anonymous types, subclassing and the fact that Java does not completely erase ALL generic declarations.
If you look closely the TypeLiteral has a protected constructor so you use an additional {} when constructing a new one which creates an anonymous subclass of TypeLiteral.
In Java generic declarations are preserved on Class and Method declarations, so if I write this.
public abstract class Class1<T>
{
}
public class Class2 extends Class1<Integer>
{
}
I can actually write code in Class1 that can figure out that its own generic type is Integer if Class2 was the subclass.
Check out the java.lang.Class API for the appropriate methods (they have Generic in the name).