Getting the Type of a generic class at runtime

How should I get the type of a parametrized class? … mmh … let me explain what mean:

import java.util.ArrayList;

public class Generic<T> {
  @Override
  public String toString() {
    return "Type Parameter is unknown.";
  }

  public static void main(String[] args) {
    System.out.println(new Generic<String>());
    System.out.println(new Generic<Integer>());
    System.out.println(new Generic<ArrayList>());
  }
}

and the output is (as expected)

Type Parameter is unknown.
Type Parameter is unknown.
Type Parameter is unknown.

But I want to have

Type Parameter is java.lang.String.
Type Parameter is java.lang.Integer.
Type Parameter is java.util.ArrayList.

The problem is that the „type erasure“ erased exactly that information. But the compiler does something with that information. Otherwise – why having that? Ok, I dont know any reflection API or getter for that. (As I said: type erasure). But maybe I can write a workaround …

Ok, what about having a member variable of type T and asking for its type?

public class Generic<T> {
  T type;

  public Class getGenericType() {
    return type.getClass();
  }

  @Override
  public String toString() {
    return "Type Parameter  is " + getGenericType().getName() + ".";
  }
}

The main-method is unchanged. But in that case I get a NullPointerException because the field is not initialized. But how to do that? Ok, no idea … but maybe I can now ask the reflection API …

Getting the field is easy

Field field = this.getClass().getField("type");</code>

but with the field I cant do any meaningful😦

System.out.println(field.getGenericType()); // T
System.out.println(field.getType()); // class java.lang.Object
System.out.println(field.getDeclaringClass()); // class MyGeneric

Sadly type erasure hit me again, so field.getType() returns the class which can catch all possibilities: java.lang.Object. If I change the type parameter from Generic to Generic (just for the String-invocation in main()) I’ll get java.lang.CharSequence. In that case the global superclass Object isnt required any more.

But the result: I dont know how to get the type parameter … Maybe I should investigate in initializing the field and asking the real object for its type.

Explore posts in the same categories: en

Schlagwörter: , ,

You can comment below, or link to this permanent URL from your own site.

10 Kommentare - “Getting the Type of a generic class at runtime”


  1. […] Jan’s Blog My personal blog about all and nothing … « Getting the Type of a generic class at runtime […]

  2. Robert Munteanu Says:

    You might be able use some code from Neal Gafter’s blocg : http://gafter.blogspot.com/search?q=super+type+token , just scan for ParametrizedType .

    Robert

  3. janmaterne Says:

    Thanks for the tip, Robert. I’ll have a look.

  4. Madhu Says:

    Hi, Even i’m searching for the solution of same problem. Please let me know if u’ve figured out the solution.

  5. janmaterne Says:

    I’ll post the „solution“ … if I found some …

  6. DavidT Says:

    http://gafter.blogspot.com/search?q=super+type+token has some solutions

    Here is something that works faster:

    public class Test {

    private Class aClass;

    public Test(Class aClass){
    this.aClass = aClass;
    }

    public static void main(String[] args) throws Exception {

    (new Test(Integer.class)).tst();

    }

    private void tst() throws Exception {
    System.out.println(„Type: “ + aClass.getName());
    }

    }

  7. DavidT Says:

    Let’s try that again but with better HTML🙂

    public class Test<T> {

    private Class<T> aClass;

    public Test(Class<T> aClass){
    this.aClass = aClass;
    }

    public static void main(String[] args) throws Exception {

    (new Test<Integer> (Integer.class)).tst();

    }

    private void tst() throws Exception {
    System.out.println(„Type: “ + aClass.getName());
    }

    }

  8. Amit G Says:

    was searching for a solution myself…
    checked both this and the link David provided.

    but I had to work with sub classes, maybe you can extrapolate on this???

    public abstract class TestGeneric<T> {

    private final Class<?> aClass;

    public TestGeneric() {

    ParameterizedType superclass = (ParameterizedType) getClass()
    .getGenericSuperclass();
    this.aClass = (Class<?>) ((ParameterizedType) superclass)
    .getActualTypeArguments()[0];
    }

    public static void main(String[] args) throws Exception {
    (new IntTest()).tst();
    (new StringTest()).tst();
    }

    public void tst() throws Exception {
    System.out.println("Type: " + aClass.getName());
    }
    }

    class IntTest extends TestGeneric<Integer>{}

    class StringTest extends TestGeneric<String>{}



Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s


%d Bloggern gefällt das: