How to get class of generic type when there is no parameter of it?

后端 未结 5 845
星月不相逢
星月不相逢 2020-12-17 21:04

I just learned about this fine looking syntax

Collections.emptyList()

to get an empty List with elements which a

相关标签:
5条回答
  • 2020-12-17 21:23

    I find out that there is one solution for getting Class<?> from T:

    public class Action<T>{
    }
    
    public Class<?> getGenericType(Object action) throws ClassNotFoundException{
       Type type =
       ((ParameterizedType)action.getClass().getGenericSuperclass())
          .getActualTypeArguments()[0];
       String sType[] = type.toString().split(" ");
    
       if(sType.length != 2)
          throw new ClassNotFoundException();
    
       return Class.forName(sType[1]);
    }
    

    The usage of code above:

    Action<String> myAction = new Action<String>();
    
    getGenericType(myAction);
    

    I did not tested this with primitive types (int, byte, boolean).

    I think that it is not very fast, but you do not have to pass Class<?> to constructor.

    EDIT:

    The usage above is not right, because generic superclass is not available for Action<String>. Generic super class will be available only for inherited class like class ActionWithParam extends Action<String>{}. This is reason why I changed my mind and now I suggest to pass class parameter to constructor, too. Thanks to newacct for correction.

    0 讨论(0)
  • 2020-12-17 21:25

    As you mentioned, Java generics are build time only. They are not used at run time.

    Because of this, the old approach you were using will be your only way to accomplish this.

    0 讨论(0)
  • 2020-12-17 21:30

    If you want the generic type at runtime you need to either have it as a field or create a sub-class of a type for a specific combination of types.

    e.g.

    List<String> list = new ArrayList<String>() {}; // creates a generic sub-type
    final Class type = (Class) ((ParameterizedType) list.getClass()
                                .getGenericSuperclass()).getActualTypeArguments()[0];
    System.out.println(type);
    

    prints

    class java.lang.String
    
    0 讨论(0)
  • 2020-12-17 21:38

    retValue.getClass().getName() will always return the runtime type of the object and not the class name of the parameter type.

    If you want to grab the parameter class, there's no other way than to use your first solution. (That is, pass the class object explicitly.)

    0 讨论(0)
  • 2020-12-17 21:42

    You can't, unfortunately. All generics and type parameters are erased in runtime. So in runtime the type of your T is simply Object

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