tags:

views:

167

answers:

4

What is the best way to retrieve the runtime value of a generic parameter for a generic class? For example:

public class MyClass<T> {

  public void printT() {
    // print the class of T, something like:
    // System.out.println(T.class.getName());
  }

}

So if I call

new MyClass<String>().printT()

it will print "String"

+4  A: 

You don't. Due to type erasure that information is (mostly) lost at runtime. If you really need the class this is what you do:

public class MyClass<T> {
  private final Class<T> clazz;

  public MyClass(Class<T> c) {
    if (c == null) {
      throw new NullPointerException("class cannot be null");
    }
    clazz = c;
  }

  public void printT() {
    System.out.println(clazz.getName());
  }
}

and then you have access to it.

cletus
Note: Your example code contains some errors, like `private final clazz;` - you forgot the type of the variable.
Jesper
+1  A: 

To achieve that, you need to add the type info, since type erasure means that T's type is not available.

public class MyClass<T> {
  private final Class<T> clazz;
  public MyClass(Class<T> clazz) {
    this.clazz=clazz;
  }

  public void printT() {
    // print the class of T, something like:
    System.out.println(this.clazz);
  }
}
Chii
+1  A: 

Java doesn't have that information at runtime, because of type erasure. You would need to pass the type as a constructor parameter to the class when the object is instantiated. There are some libraries and languages which can help you to do that with less typing: Guice can do it and also Scala can do it.

Esko Luontola
A: 

As mentioned before, you can't obtain type information at that example because of type erasure.

However, you can redesign your classes hierarchy in order to have a generic superclass/interface and make child classes directly define type parameter at their definitions:

package com;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;

public class AAA {
    public static void main(String[] args) throws Exception {
     Object target = new MyClass<Integer>() {}; // child class that explicitly defines superclass type parameter is declared here
     ParameterizedType type = (ParameterizedType) target.getClass().getGenericSuperclass();
     System.out.println(Arrays.toString(type.getActualTypeArguments()));
    }
}

class MyClass<T> {
}
denis.zhdanov