Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Class<T> from List<T>

I feel utterly silly for having to ask this, but I'm failing to understand why doesn't the following Java code compile:

void <T> doSomething(List<T> items) {
    Class<? extends T> clazz = items.get(0).getClass();
    ...
}

From Java doc:

The actual result type is Class< ? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called. For example, no cast is required in this code fragment:

Number n = 0; Class< ? extends Number> c = n.getClass();

EDIT:

  1. Found this nice explanation of what erasure of the static type means.

  2. There's a way to preserve generic type information using subclasses, known as super type token. A now deleted answer helpfully pointed out that Guava library has a convenient utility for exploiting this.

  3. Here's a great article on extracting generic types reflectively and a nice lib, called GenTyRef, simplifying it

  4. I forked GenTyRef to add support for working with AnnotatedTypes (introduced in Java 8). It's called GeantyRef (and it's in Maven Central)

like image 583
kaqqao Avatar asked May 23 '16 08:05

kaqqao


People also ask

How do I get my class name from T?

Now you can retrieve the type of T at runtime: Type mySuperclass = myFoo. getClass(). getGenericSuperclass(); Type tType = ((ParameterizedType)mySuperclass).

How do I get a class instance of generic type T?

The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. A solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.

What is the meaning of class T?

In Java there's a single metaclass: Class . Its instances (only one per type exists) are used to represent classes and interfaces, therefore the T in Class<T> refers to the type of the class or interface that the current instance of Class represents.

What is class T type in Java?

T is type parameters (also called type variables); delimited by angle brackets (<>), follows the class name. T is just a symbol, like a variable name (can be any name) declared during writing of the class file.


1 Answers

The erasure of the static type of items.get(0) is Object (since T is erased during compilation).

Therefore items.get(0).getClass() returns a Class<? extends Object>, not a Class<? extends T>, which explains why your attempted assignment fails.

This will pass compilation :

Class<? extends Object> clazz = items.get(0).getClass();

If you want the Class of the generic parameter to be known by that method, you can pass it as an additional argument.

void doSomething(List<T> items, Class<T> clazz) {

}
like image 117
Eran Avatar answered Sep 23 '22 12:09

Eran