Get type of a generic parameter in Java with refle

2018-12-31 07:35发布

Is it possible to get the type of a generic parameter?

An example:

public final class Voodoo {
    public static void chill(List<?> aListWithTypeSpiderMan) {
        // Here I'd like to get the Class-Object 'SpiderMan'
        Class typeOfTheList = ???;
    }

    public static void main(String... args) {
        chill(new ArrayList<SpiderMan>());
    }
}

16条回答
无色无味的生活
2楼-- · 2018-12-31 08:26

There is a solution actually, by applying the "anonymous class" trick and the ideas from the Super Type Tokens:

public final class Voodoo {
    public static void chill(final List<?> aListWithSomeType) {
        // Here I'd like to get the Class-Object 'SpiderMan'
        System.out.println(aListWithSomeType.getClass().getGenericSuperclass());
        System.out.println(((ParameterizedType) aListWithSomeType
            .getClass()
            .getGenericSuperclass()).getActualTypeArguments()[0]);
    }
    public static void main(String... args) {
        chill(new ArrayList<SpiderMan>() {});
    }
}
class SpiderMan {
}

The trick lies in the creation of an anonymous class, new ArrayList<SpiderMan>() {}, in the place of the original (simple) new ArrayList<SpiderMan>(). The use of an anoymous class (if possible) ensures that the compiler retains information about the type argument SpiderMan given to the type parameter List<?>. Voilà !

查看更多
十年一品温如言
3楼-- · 2018-12-31 08:26

Just for me reading this snippet of code was hard, I just divided it into 2 readable lines :

// assuming that the Generic Type parameter is of type "T"
ParameterizedType p = (ParameterizedType) getClass().getGenericSuperclass();
Class<T> c =(Class<T>)p.getActualTypeArguments()[0];

I wanted to create an instance of the Type parameter without having any parameters to my method :

publc T getNewTypeInstance(){
    ParameterizedType p = (ParameterizedType) getClass().getGenericSuperclass();
    Class<T> c =(Class<T>)p.getActualTypeArguments()[0];

    // for me i wanted to get the type to create an instance
    // from the no-args default constructor
    T t = null;
    try{
        t = c.newInstance();
    }catch(Exception e){
        // no default constructor available
    }
    return t;
}
查看更多
看风景的人
4楼-- · 2018-12-31 08:28

Actually I got this to work. Consider the following snippet:

Method m;
Type[] genericParameterTypes = m.getGenericParameterTypes();
for (int i = 0; i < genericParameterTypes.length; i++) {
     if( genericParameterTypes[i] instanceof ParameterizedType ) {
                Type[] parameters = ((ParameterizedType)genericParameterTypes[i]).getActualTypeArguments();
//parameters[0] contains java.lang.String for method like "method(List<String> value)"

     }
 }

I'm using jdk 1.6

查看更多
其实,你不懂
5楼-- · 2018-12-31 08:29

This is impossible because generics in Java are only considered at compile time. Thus, the Java generics are just some kind of pre-processor. However you can get the actual class of the members of the list.

查看更多
登录 后发表回答