Java 从泛型T派生类

Java 从泛型T派生类,java,generics,reflection,derived-class,Java,Generics,Reflection,Derived Class,我有一个参数化的hibernate dao,它执行基本的crud操作,当参数化的dao被用作一个委托来完成给定dao的基本crud操作时 public class HibernateDao <T, ID extends Serializable> implements GenericDao<T, ID> 我知道: T.getClass() 不存在,但是否有任何方法可以在运行时从T派生正确的类对象 我已经研究了泛型和反射,但还没有找到合适的解决方案,也许我遗漏了一些东西

我有一个参数化的hibernate dao,它执行基本的crud操作,当参数化的dao被用作一个委托来完成给定dao的基本crud操作时

public class HibernateDao <T, ID extends Serializable> implements GenericDao<T, ID>
我知道:

T.getClass()
不存在,但是否有任何方法可以在运行时从T派生正确的类对象

我已经研究了泛型和反射,但还没有找到合适的解决方案,也许我遗漏了一些东西


谢谢。

您可以将该类作为构造函数参数传递

public class HibernateDao <T, ID extends Serializable> implements GenericDao<T, ID> {

    private final Class<? extends T> type;

    public HibernateDao(Class<? extends T> type) {
        this.type = type;
    }

    // ....

}
公共类HibernateDao实现GenericDao{

private final Class有一种方法可以使用反射来计算类型参数
T
Class

private Class<T> persistentClass = (Class<T>)
    ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
私有类persistentClass=(类)
((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
以下是我使用它的方式:

public class GenericDaoJPA<T> implements GenericDao<T> {

    @PersistenceContext
    protected EntityManager entityManager;

    protected Class<T> persistentClass = figureOutPersistentClass();

    private Class<T> figureOutPersistentClass() {
        Class<T> clazz = (Class<T>)((ParameterizedType) (getClass().getGenericSuperclass())).getActualTypeArguments()[0];
        log.debug("persistentClass set to {}", clazz.getName());
        return clazz;
    }

    public List<T> findAll() {
        Query q = entityManager.createQuery("SELECT e FROM " + persistentClass.getSimpleName() + " e");
        return (List<T>) q.getResultList();
    }

}
公共类GenericDaoJPA实现GenericDao{
@持久上下文
受保护的实体管理器实体管理器;
受保护类persistentClass=figureOutPersistentClass();
私有类figureOutPersistentClass(){
类clazz=(类)(参数化类型)(getClass().getGenericSuperclass()).getActualTypeArguments()[0];
debug(“persistentClass设置为{}”,clazz.getName());
回击声;
}
公共列表findAll(){
Query q=entityManager.createQuery(“从”+persistentClass.getSimpleName()+“e”中选择e”);
返回(列表)q.getResultList();
}
}
我想只有当您的
ConcreteEntityDao
HibernateDao
的直接超类时,这种方法才有效


我在这里找到了它:www.greggbolinger.com/blog/2008/04/17/1208457000000.html

是的,这是我的一个解决方案。如果可能的话,我希望能够从T派生类,而不添加类依赖项。@bowsie:我理解你的痛苦。不幸的是,编译器完成后会擦除T的所有痕迹。这称为类型擦除:@AdamPaynter很难向新手解释擦除为什么你可以使用你眼前看到的
。@Nishant:你说得对。我在学习Java时也遇到过同样的情况。它似乎应该在那里!违反了最小惊讶原则。:)这只在方法(堆栈位置)中有效这将创建参数化对象。如果从另一个方法接收参数化对象,它将不起作用。我不确定我是否理解。您能更详细地解释一下吗?对web应用程序开发有什么影响吗?当您直接对泛型类进行子类化时,这非常有效。如果您有多个inh级别因此,您需要使用
getSuperClass
figureOutPersistentClass
中解释它们。
public class GenericDaoJPA<T> implements GenericDao<T> {

    @PersistenceContext
    protected EntityManager entityManager;

    protected Class<T> persistentClass = figureOutPersistentClass();

    private Class<T> figureOutPersistentClass() {
        Class<T> clazz = (Class<T>)((ParameterizedType) (getClass().getGenericSuperclass())).getActualTypeArguments()[0];
        log.debug("persistentClass set to {}", clazz.getName());
        return clazz;
    }

    public List<T> findAll() {
        Query q = entityManager.createQuery("SELECT e FROM " + persistentClass.getSimpleName() + " e");
        return (List<T>) q.getResultList();
    }

}