Get actual type of generic type argument on abstract superclass

后端 未结 6 1154
自闭症患者
自闭症患者 2020-11-27 20:08

I have a class like:

public abstract class BaseDao {

  protected Class getClazz() {
     return T.class;
  }

  /         


        
6条回答
  •  悲&欢浪女
    2020-11-27 20:47

    It's definitely possible to extract it from Class#getGenericSuperclass() because it's not defined during runtime, but during compiletime by FooDao extends BaseDao.

    Here's a kickoff example how you could extract the desired generic super type in the constructor of the abstract class, taking a hierarchy of subclasses into account (along with a real world use case of applying it on generic EntityManager methods without the need to explicitly supply the type):

    public abstract class BaseDao {
    
        @PersistenceContext
        private EntityManager em;
    
        private Class type;
    
        @SuppressWarnings("unchecked") // For the cast on Class.
        public BaseDao() {
            Type type = getClass().getGenericSuperclass();
    
            while (!(type instanceof ParameterizedType) || ((ParameterizedType) type).getRawType() != BaseDao.class) {
                if (type instanceof ParameterizedType) {
                    type = ((Class) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
                } else {
                    type = ((Class) type).getGenericSuperclass();
                }
            }
    
            this.type = (Class) ((ParameterizedType) type).getActualTypeArguments()[0];
        }
    
        public E find(Long id) {
            return em.find(type, id);
        }
    
        public List list() {
            return em.createQuery(String.format("SELECT e FROM %s e ORDER BY id", type.getSimpleName()), type).getResultList();
        }
    
        // ...
    }
    

提交回复
热议问题