Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using getActualTypeArguments in a generic context

There are other related questions e.g. 6624113, 3403909, 4516891 but my question is simpler and more specific.

I want to know at runtime what type my class was parameterized with - I want a Class object of the type of the type parameter. Because of type erasure, the expression T.class doesn't work, and there is no function like typeof(T) in C# to get it.

However, there is some "uber-reflection" available via ParameterizedType and related classes, which gets me almost all of the way there.

import java.lang.reflect.ParameterizedType;

public class MyClass<T> {
    public static void main( String[] args ) {
        new MyClass<Integer>().printTypeParam();
    }

    public void printTypeParam() {
        class DummyT extends MyClass<T> {}
        class DummyString extends MyClass<String> {}

        ParameterizedType ptT =
            ((ParameterizedType) DummyT.class.getGenericSuperclass() );

        ParameterizedType ptString =
            ((ParameterizedType) DummyString.class.getGenericSuperclass() );

        System.out.println( "DummyT: " + ptT + " " + ptT.getActualTypeArguments()[0] );
        System.out.println( "DummyString: " + ptString + " " + ptString.getActualTypeArguments()[0] );

    }
}

When I run the above I see this output:

DummyT: MyClass<T> T
DummyString: MyClass<java.lang.String> class java.lang.String

As you can see, this works for when the type arguments are known at compile-time at the line of code containing the call to getGenericSuperClass, but where that call is itself dealing with generics it simply prints the name of the type parameter.

Is there any way I can get the first line to print java.lang.Integer instead of T?

like image 637
Andy Balaam Avatar asked Nov 04 '11 16:11

Andy Balaam


1 Answers

You can't, plain and simple. Integer is not reified, it is completely erased. If you don't believe me, compile the file once with Integer and once with Long. The two binary class files will be absolutely identical.

Type erasure is a harsh reality that you won't be able to get around. I suggest you rethink why you need it instead of going down the path of introducing hacks to try to avoid it.

Useful AngelikaLanger Generics FAQ topics:

  • What is type erasure?
  • What is reification?
  • What is a reifiable type?
like image 144
Mark Peters Avatar answered Sep 23 '22 13:09

Mark Peters