Java 获取抽象超类上泛型类型参数的实际类型

Java 获取抽象超类上泛型类型参数的实际类型,java,generics,jpa,dao,Java,Generics,Jpa,Dao,我有一门课,像: public abstract class BaseDao<T extends PersistentObject> { protected Class<T> getClazz() { return T.class; } // ... } 公共抽象类BaseDao{ 受保护类getClazz(){ 返回T.class; } // ... } 但是编译器告诉T.class:类型参数T的非法类文本 如何获取T类?以安全的方式对该

我有一门课,像:

public abstract class BaseDao<T extends PersistentObject> {

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

  // ...

}
公共抽象类BaseDao{
受保护类getClazz(){
返回T.class;
}
// ...
}
但是编译器告诉
T.class
类型参数T的非法类文本


如何获取
T
类?

以安全的方式对该问题进行排序的常见方法是添加一个构造函数来存储该类型的类。 在您的上下文中的示例:

public abstract class BaseDao<T extends PersistentObject> {
  private Class<T> classT;

  BaseDao(Class<T> classT){
    this.classT=classT;
  }

  protected Class<T> getClazz() {
     return classT;
  }

  // ...

}
公共抽象类BaseDao{
私人班级;
BaseDao(类T){
this.classT=classT;
}
受保护类getClazz(){
返回类T;
}
// ...
}

以安全方式对该问题进行排序的常见方法是添加一个构造函数来存储该类型的类。 在您的上下文中的示例:

public abstract class BaseDao<T extends PersistentObject> {
  private Class<T> classT;

  BaseDao(Class<T> classT){
    this.classT=classT;
  }

  protected Class<T> getClazz() {
     return classT;
  }

  // ...

}
公共抽象类BaseDao{
私人班级;
BaseDao(类T){
this.classT=classT;
}
受保护类getClazz(){
返回类T;
}
// ...
}

如果您的类是抽象类,您可以尝试以下方法:

public class<T> getClassOfT() {
    final ParameterizedType type = (ParameterizedType) this.getClass()
            .getGenericSuperclass();
    Class<T> clazz = (Class<T>) type.getActualTypeArguments()[0];
    return clazz;
}
公共类getClassOfT(){
最终ParameteredType类型=(ParameteredType)this.getClass()
.getGenericSuperclass();
类clazz=(类)type.getActualTypeArguments()[0];
回击声;
}
只有当实例是一个直接子类,并且您想要的类的类型是第一个(请参见[0])时,这才有效

如果有大量的dao层次结构,可以递归地尝试fidn BaseDao并获取参数化类型

参见示例(参见底部的输出)


为我糟糕的英语干杯并致歉

如果你的课是抽象的,你可以试试这个:

public class<T> getClassOfT() {
    final ParameterizedType type = (ParameterizedType) this.getClass()
            .getGenericSuperclass();
    Class<T> clazz = (Class<T>) type.getActualTypeArguments()[0];
    return clazz;
}
公共类getClassOfT(){
最终ParameteredType类型=(ParameteredType)this.getClass()
.getGenericSuperclass();
类clazz=(类)type.getActualTypeArguments()[0];
回击声;
}
只有当实例是一个直接子类,并且您想要的类的类型是第一个(请参见[0])时,这才有效

如果有大量的dao层次结构,可以递归地尝试fidn BaseDao并获取参数化类型

参见示例(参见底部的输出)


为我糟糕的英语干杯并道歉

确实可以从中提取它,因为它不是在运行时定义的,而是在编译时由
FooDao扩展BaseDao
定义的

下面是一个开始示例,您可以如何在抽象类的构造函数中提取所需的泛型超类型,同时考虑子类的层次结构(以及在泛型
EntityManager
方法上应用它而无需显式提供类型的实际用例):

公共抽象类BaseDao{
@持久上下文
私人实体管理者;
私人阶级类型;
@SuppressWarnings(“未选中”)//用于强制转换类。
公共数据库(){
类型Type=getClass().getGenericSuperclass();
while(!(类型instanceof ParameterizedType)| |((ParameterizedType)类型).getRawType()!=BaseDao.class){
if(类型instanceof ParameterizedType){
类型=((类)((参数化类型)类型).getRawType()).getGenericSuperclass();
}否则{
类型=((类)类型).getGenericSuperclass();
}
}
this.type=(类)((ParameterizedType)类型).getActualTypeArguments()[0];
}
公共E查找(长id){
返回em.find(类型,id);
}
公开名单(){
返回em.createQuery(String.format(“按id从%s中选择e”,type.getSimpleName()),type).getResultList();
}
// ...
}

当然可以从中提取它,因为它不是在运行时定义的,而是在编译时由
FooDao扩展BaseDao
定义的

下面是一个开始示例,您可以如何在抽象类的构造函数中提取所需的泛型超类型,同时考虑子类的层次结构(以及在泛型
EntityManager
方法上应用它而无需显式提供类型的实际用例):

公共抽象类BaseDao{
@持久上下文
私人实体管理者;
私人阶级类型;
@SuppressWarnings(“未选中”)//用于强制转换类。
公共数据库(){
类型Type=getClass().getGenericSuperclass();
while(!(类型instanceof ParameterizedType)| |((ParameterizedType)类型).getRawType()!=BaseDao.class){
if(类型instanceof ParameterizedType){
类型=((类)((参数化类型)类型).getRawType()).getGenericSuperclass();
}否则{
类型=((类)类型).getGenericSuperclass();
}
}
this.type=(类)((ParameterizedType)类型).getActualTypeArguments()[0];
}
公共E查找(长id){
返回em.find(类型,id);
}
公开名单(){
返回em.createQuery(String.format(“按id从%s中选择e”,type.getSimpleName()),type).getResultList();
}
// ...
}
您可以查看以下内容:

Class<T> t = (Class<T>)TypeResolver.resolveRawArgument(BaseDao.class, getClass());
Class t=(Class)TypeResolver.resolveRawArgument(BaseDao.Class,getClass());
您可以查看以下内容:

Class<T> t = (Class<T>)TypeResolver.resolveRawArgument(BaseDao.class, getClass());
Class t=(Class)TypeResolver.resolveRawArgument(BaseDao.Class,getClass());

事实上,这并不像看上去那么容易。当您具有丰富类型层次结构并希望在超类型中获取泛型参数时,会出现问题。例如,您可能具有以下层次结构:

public abstract class BaseDao<T extends BaseEntity> {
...
}

public abstract class SpecialDao<X extends SomeType, E extends BaseEntity> extends BaseDao<E> {
...
}

public class MyDao extends SpecialDao<TypeImpl, EntityImpl> {
...
}

事实上,这并不像看上去那么容易。当您具有丰富类型层次结构并希望在超类型中获取泛型参数时,会出现问题。例如,您可能具有以下层次结构:

public abstract class BaseDao<T extends BaseEntity> {
...
}

public abstract class SpecialDao<X extends SomeType, E extends BaseEntity> extends BaseDao<E> {
...
}

public class MyDao extends SpecialDao<TypeImpl, EntityImpl> {
...
}

如果Spring framework可用,您可以执行以下操作:

import org.springframework.core.GenericTypeResolver;

public abstract class BaseDao<T extends PersistentObject> {

    protected Class<T> getClazz() {
        return (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), BaseDao.class);
    }

}
import org.springframework.core.GenericTypeResolver;
公共抽象类BaseDao{