tags:

views:

134

answers:

5

I have a generics class Foo<T>. In a method of Foo, i want to get the class instance of type T. But i just can't call T.class

Please tell me your preferred way to get around with the T.class ?

+4  A: 

You can't do it because of type erasure.

See also: http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens

Konrad Garus
+1  A: 

It is not possible to get the class of a generic type parameter within the generic code. Type erasure prevents it.

The normal workaround is to explicitly pass the Class object for the actual type as a parameter to the generic type's constructor. For example:

public class Foo<T> {

    private Class<T> clazz;

    public Foo(Class<T> clazz) {
        this.clazz = clazz;
    }

    public void doSomething(...) {
        T myT = clazz.newInstance();
        ...
    }
}
Stephen C
+5  A: 

The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. I suggest reading the chapter about type erasure in the Java Tutorial for more details.

A popular solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.

class Foo<T> {
    final Class<T> typeParameterClass;

    public Foo(Class<T> typeParameterClass) {
        this.typeParameterClass = typeParameterClass;
    }

    public void bar() {
        // you can access the typeParameterClass here and do whatever you like
    }
}
Zsolt Török
+3  A: 

A standard approach/workaround/solution is to add a class object to the constructor(s), like:

 public class Foo<T> {

    privat Class<T> type;
    public Foo(Class<T> type) {
      this.type = type;
    }

    public Class<T> getType() {
      return type;
    }

    public T newInstance() {
      return type.newInstance();
    }
 }
Andreas_D
+1  A: 

A better route than the Class the others suggested is to pass in an object that can do what you would have done with the Class, e.g., create a new instance.

interface Factory<T> {
  T apply();
}

<T> void List<T> make10(Factory<T> factory) {
  List<T> result = new ArrayList<T>();
  for (int a = 0; a < 10; a++)
    result.add(factory.apply());
  return result;
}

class FooFactory implements Factory<Foo> {
  public Foo apply() {
    return new Foo();
  }
}

List<Foo> foos = make10(new FooFactory());
Ricky Clarkson