Java: how do I get a class literal from a generic type?

You can’t due to type erasure.

Java generics are little more than syntactic sugar for Object casts. To demonstrate:

List<Integer> list1 = new ArrayList<Integer>();
List<String> list2 = (List<String>)list1;
list2.add("foo"); // perfectly legal

The only instance where generic type information is retained at runtime is with Field.getGenericType() if interrogating a class’s members via reflection.

All of this is why Object.getClass() has this signature:

public final native Class<?> getClass();

The important part being Class<?>.

To put it another way, from the Java Generics FAQ:

Why is there no class literal for concrete parameterized types?

Because parameterized type has no exact runtime type representation.

A class literal denotes a Class
object that represents a given type.
For instance, the class literal
String.class denotes the Class
object that represents the type
String and is identical to the
Class object that is returned when
method getClass is invoked on a
String object. A class literal can
be used for runtime type checks and
for reflection.

Parameterized types lose their type
arguments when they are translated to
byte code during compilation in a
process called type erasure . As a
side effect of type erasure, all
instantiations of a generic type share
the same runtime representation,
namely that of the corresponding raw
type . In other words, parameterized
types do not have type representation
of their own. Consequently, there is
no point in forming class literals
such as List<String>.class ,
List<Long>.class and List<?>.class
, since no such Class objects exist.
Only the raw type List has a Class
object that represents its runtime
type. It is referred to as
List.class.

Leave a Comment