The following code:
public static void main(String args[]) throws NoSuchFieldException {
List<Integer> li = new ArrayList<Integer>();
ParameterizedType apType = (ParameterizedType) li.getClass().getGenericSuperclass();
Type[] typeArguments = apType.getActualTypeArguments();
int _i = 0;
for (Type type : typeArguments) {
System.out.format("parameterized type %d is: %s", ++_i, type);
}
}
produces:
parameterized type 1 is: E
- Do I understand correctly that this is because of the effects of Type Erasure and that it should be interpreted as "unknown", given that E is the type parameter name?
- It strikes me as odd that I somehow have to interpret the name "E" (and I suppose "S", "U", etc. if more exist) specially. What if I have a class "E"? Moreover the method name is get_Actual_TypeArguments. Given that type parameters serve as placeholders much like variables I find it very odd that a method should return the name of the variable. Am I missing something here?
Also, it's not clear to me why I can cast the superclass to ParameterizedType but not the class itself. Trying to cast the result of li.getClass() as a ParameterizedType yields the following compile time error:
required: ParameterizedType found: Class where CAP#1 is a fresh type-variable: CAP#1 extends List from capture of ? extends List
I've seen this relevant SO post but it hasn't enlightened me.
All instances of a generic class share the same runtime class:
Put differently, the runtime does not track the actual type arguments used to instantiate a generic class. However, it does know the types declared in the source code, and that's what getGenericSuperclass() and friends return. So if you have a class:
The expression
returns
In contrast, if you declare
the same expression returns
So yes, getGenericSuperclass returns the actual type parameters as declared in the source code, but those type parameters may contain type variables declared elsewhere.
A
ParametrizedType
object represents a compile time type with a non-empty list of type arguments, aClass
object a runtime type (which doesn't have any type arguments). Therefore, aClass
is not aParametrizedType
.