How do I get a class instance of generic type T?

前端 未结 22 1236
猫巷女王i
猫巷女王i 2020-11-21 11:03

I have a generics class, Foo. In a method of Foo, I want to get the class instance of type T, but I just can\'t call T.

相关标签:
22条回答
  • 2020-11-21 11:48

    I'm using workaround for this:

    class MyClass extends Foo<T> {
    ....
    }
    
    MyClass myClassInstance = MyClass.class.newInstance();
    
    0 讨论(0)
  • 2020-11-21 11:49

    I had this problem in an abstract generic class. In this particular case, the solution is simpler:

    abstract class Foo<T> {
        abstract Class<T> getTClass();
        //...
    }
    

    and later on the derived class:

    class Bar extends Foo<Whatever> {
        @Override
        Class<T> getTClass() {
            return Whatever.class;
        }
    }
    
    0 讨论(0)
  • 2020-11-21 11:50

    Actually, I suppose you have a field in your class of type T. If there's no field of type T, what's the point of having a generic Type? So, you can simply do an instanceof on that field.

    In my case, I have a

    List<T> items;
    in my class, and I check if the class type is "Locality" by

    if (items.get(0) instanceof Locality) ...
    

    Of course, this only works if the total number of possible classes is limited.

    0 讨论(0)
  • 2020-11-21 11:52

    This question is old, but now the best is use google Gson.

    An example to get custom viewModel.

    Class<CustomViewModel<String>> clazz = new GenericClass<CustomViewModel<String>>().getRawType();
    CustomViewModel<String> viewModel = viewModelProvider.get(clazz);
    

    Generic type class

    class GenericClass<T>(private val rawType: Class<*>) {
    
        constructor():this(`$Gson$Types`.getRawType(object : TypeToken<T>() {}.getType()))
    
        fun getRawType(): Class<T> {
            return rawType as Class<T>
        }
    }
    
    0 讨论(0)
  • 2020-11-21 11:53

    That is pretty straight forward. If you need from within the same class:

    Class clazz = this.getClass();
    ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
    try {
            Class typeClass = Class.forName( parameterizedType.getActualTypeArguments()[0].getTypeName() );
            // You have the instance of type 'T' in typeClass variable
    
            System.out.println( "Class instance name: "+  typeClass.getName() );
        } catch (ClassNotFoundException e) {
            System.out.println( "ClassNotFound!! Something wrong! "+ e.getMessage() );
        }
    
    0 讨论(0)
  • 2020-11-21 11:54

    I was looking for a way to do this myself without adding an extra dependency to the classpath. After some investigation I found that it is possible as long as you have a generic supertype. This was OK for me as I was working with a DAO layer with a generic layer supertype. If this fits your scenario then it's the neatest approach IMHO.

    Most generics use cases I've come across have some kind of generic supertype e.g. List<T> for ArrayList<T> or GenericDAO<T> for DAO<T>, etc.

    Pure Java solution

    The article Accessing generic types at runtime in Java explains how you can do it using pure Java.

    @SuppressWarnings("unchecked")
    public GenericJpaDao() {
      this.entityBeanType = ((Class) ((ParameterizedType) getClass()
          .getGenericSuperclass()).getActualTypeArguments()[0]);
    }
    

    Spring solution

    My project was using Spring which is even better as Spring has a handy utility method for finding the type. This is the best approach for me as it looks neatest. I guess if you weren't using Spring you could write your own utility method.

    import org.springframework.core.GenericTypeResolver;
    
    public abstract class AbstractHibernateDao<T extends DomainObject> implements DataAccessObject<T>
    {
    
        @Autowired
        private SessionFactory sessionFactory;
    
        private final Class<T> genericType;
    
        private final String RECORD_COUNT_HQL;
        private final String FIND_ALL_HQL;
    
        @SuppressWarnings("unchecked")
        public AbstractHibernateDao()
        {
            this.genericType = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), AbstractHibernateDao.class);
            this.RECORD_COUNT_HQL = "select count(*) from " + this.genericType.getName();
            this.FIND_ALL_HQL = "from " + this.genericType.getName() + " t ";
        }
    
    0 讨论(0)
提交回复
热议问题