Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine the class of a generic type?

Tags:

java

generics

I'm creating a generic class and in one of the methods I need to know the Class of the generic type currently in use. The reason is that one of the method's I call expects this as an argument.

Example:

public class MyGenericClass<T> {   public void doSomething() {     // Snip...     // Call to a 3rd party lib     T bean = (T)someObject.create(T.class);     // Snip...   } } 

Clearly the example above doesn't work and results in the following error: Illegal class literal for the type parameter T.

My question is: does someone know a good alternative or workaround for this?

like image 600
Jaap Coomans Avatar asked Oct 08 '08 13:10

Jaap Coomans


People also ask

How do you find the class object of a generic type?

Pass the class object instead and it's easy. The idea here is that since you can't extract the type parameter from the object, you have to do it the other way around: start with the class and then manipulate the object to match the type parameter.

How do you identify a generic type?

Use the IsGenericType property to determine whether the type is generic, and use the IsGenericTypeDefinition property to determine whether the type is a generic type definition. Get an array that contains the generic type arguments, using the GetGenericArguments method.

How do you define generic classes?

A Generic class simply means that the items or functions in that class can be generalized with the parameter(example T) to specify that we can add any type as a parameter in place of T like Integer, Character, String, Double or any other user-defined type.

How do you indicate that a class has a generic type parameter?

A generic type is declared by specifying a type parameter in an angle brackets after a type name, e.g. TypeName<T> where T is a type parameter.


2 Answers

Still the same problems : Generic informations are erased at runtime, it cannot be recovered. A workaround is to pass the class T in parameter of a static method :

public class MyGenericClass<T> {      private final Class<T> clazz;      public static <U> MyGenericClass<U> createMyGeneric(Class<U> clazz) {         return new MyGenericClass<U>(clazz);     }      protected MyGenericClass(Class<T> clazz) {         this.clazz = clazz;     }      public void doSomething() {         T instance = clazz.newInstance();     } } 

It's ugly, but it works.

like image 97
Nicolas Avatar answered Oct 14 '22 01:10

Nicolas


I was just pointed to this solution:

import java.lang.reflect.ParameterizedType;  public abstract class A<B> {     public Class<B> g() throws Exception {         ParameterizedType superclass =             (ParameterizedType) getClass().getGenericSuperclass();          return (Class<B>) superclass.getActualTypeArguments()[0];     } } 

This works if A is given a concrete type by a subclass:

new A<String>() {}.g() // this will work  class B extends A<String> {} new B().g() // this will work  class C<T> extends A<T> {} new C<String>().g() // this will NOT work 
like image 24
Christoph Avatar answered Oct 14 '22 00:10

Christoph