Get type of a generic parameter in Java with reflection

后端 未结 18 1972
死守一世寂寞
死守一世寂寞 2020-11-22 05:56

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

An example:

public final class Voodoo {
    public static void chill(List aListWithTy         


        
相关标签:
18条回答
  • 2020-11-22 06:14

    You can get the type of a generic parameter with reflection like in this example that I found here:

    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    
    public class Home<E> {
        @SuppressWarnings ("unchecked")
        public Class<E> getTypeParameterClass(){
            Type type = getClass().getGenericSuperclass();
            ParameterizedType paramType = (ParameterizedType) type;
            return (Class<E>) paramType.getActualTypeArguments()[0];
        }
    
        private static class StringHome extends Home<String>{}
        private static class StringBuilderHome extends Home<StringBuilder>{}
        private static class StringBufferHome extends Home<StringBuffer>{}   
    
        /**
         * This prints "String", "StringBuilder" and "StringBuffer"
         */
        public static void main(String[] args) throws InstantiationException, IllegalAccessException {
            Object object0 = new StringHome().getTypeParameterClass().newInstance();
            Object object1 = new StringBuilderHome().getTypeParameterClass().newInstance();
            Object object2 = new StringBufferHome().getTypeParameterClass().newInstance();
            System.out.println(object0.getClass().getSimpleName());
            System.out.println(object1.getClass().getSimpleName());
            System.out.println(object2.getClass().getSimpleName());
        }
    }
    
    0 讨论(0)
  • 2020-11-22 06:15

    One construct, I once stumbled upon looked like

    Class<T> persistentClass = (Class<T>)
       ((ParameterizedType)getClass().getGenericSuperclass())
          .getActualTypeArguments()[0];
    

    So there seems to be some reflection-magic around that I unfortunetly don't fully understand... Sorry.

    0 讨论(0)
  • 2020-11-22 06:15

    Nope, that is not possible. Due to downwards compatibility issues, Java's generics are based on type erasure, i.a. at runtime, all you have is a non-generic List object. There is some information about type parameters at runtime, but it resides in class definitions (i.e. you can ask "what generic type does this field's definition use?"), not in object instances.

    0 讨论(0)
  • 2020-11-22 06:15

    No it isn't possible.

    You can get a generic type of a field given a class is the only exception to that rule and even that's a bit of a hack.

    See Knowing type of generic in Java for an example of that.

    0 讨论(0)
  • 2020-11-22 06:17

    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;
    }
    
    0 讨论(0)
  • 2020-11-22 06:19

    As pointed out by @bertolami, it's not possible to us a variable type and get its future value (the content of typeOfList variable).

    Nevertheless, you can pass the class as parameter on it like this:

    public final class voodoo {
        public static void chill(List<T> aListWithTypeSpiderMan, Class<T> clazz) {
            // Here I'd like to get the Class-Object 'SpiderMan'
            Class typeOfTheList = clazz;
        }
    
        public static void main(String... args) {
            chill(new List<SpiderMan>(), Spiderman.class );
        }
    }
    

    That's more or less what Google does when you have to pass a class variable to the constructor of ActivityInstrumentationTestCase2.

    0 讨论(0)
提交回复
热议问题