It’s definitely possible to extract it from Class#getGenericSuperclass()
because it’s not defined during runtime, but during compiletime by FooDao extends BaseDao<Foo>
.
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<E extends BaseEntity> {
@PersistenceContext
private EntityManager em;
private Class<E> type;
@SuppressWarnings("unchecked") // For the cast on Class<E>.
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<E>) ((ParameterizedType) type).getActualTypeArguments()[0];
}
public E find(Long id) {
return em.find(type, id);
}
public List<E> list() {
return em.createQuery(String.format("SELECT e FROM %s e ORDER BY id", type.getSimpleName()), type).getResultList();
}
// ...
}