Java 如何从类对象获取(泛型)类型

Java 如何从类对象获取(泛型)类型,java,templates,generics,Java,Templates,Generics,我想这样做: 但反过来说。所以我想得到类对象的类型。在伪代码中,我想做如下操作: public class ExampleClass { public static final Class<?>[] classes = new Class[]{MyClass1.class, MyClass2.class, MyClass3.class, MyClass4.class, MyClass5.class}; public void myMethod() {

我想这样做:

但反过来说。所以我想得到类对象的类型。在伪代码中,我想做如下操作:

public class ExampleClass {

    public static final Class<?>[] classes = new Class[]{MyClass1.class,
    MyClass2.class, MyClass3.class, MyClass4.class, MyClass5.class};

    public void myMethod() {
        for (Class<?> c : DataBaseConfigUtils.classes ) {
            MyObjectDAO<c.getType(), Integer> myObjectDAO = getMyObjectDAO(c);
            ArrayList<c.getType()> list = myObjectDAO.queryAll();
            for (c.getType() element : list) {
                processElement(element);
            }

        }
    }

    public <T> MyObjectDAO<T, Integer> getMyObjectDAO(Class<T> c) {
        return doSomething(c);
    }
}
公共类示例类{
公共静态最终类[]类=新类[]{MyClass1.Class,
MyClass2.class、MyClass3.class、MyClass4.class、MyClass5.class};
公共方法(){
用于(c类:DataBaseConfigUtils.classes){
MyObjectDAO MyObjectDAO=getMyObjectDAO(c);
ArrayList list=myObjectDAO.queryAll();
for(c.getType()元素:list){
过程元素(元素);
}
}
}
公共MyObjectDAO getMyObjectDAO(c类){
返回剂量测定法(c);
}
}

但是没有什么比得上
Class.getType()
。那么如何获取类对象的类型呢?

这在Java中是不可能的。该类型仅在编译期间使用,并被擦除。此信息不存在于字节码或运行时环境中

Java语言中引入了泛型以提供更紧密的类型 在编译时进行检查,以支持泛型编程。到 实现泛型,Java编译器将类型擦除应用于:

  • 如果类型参数是无界的,则用其边界或对象替换泛型类型中的所有类型参数。产生的字节码, 因此,只包含普通类、接口和方法
  • 如有必要,插入类型强制转换以保持类型安全
  • 生成桥接方法以在扩展泛型类型中保留多态性
类型擦除可确保不会为参数化类型创建新类 类型;因此,泛型不会产生运行时开销


您的通用方法
getMyObjectDAO
似乎回答了您自己的问题。如果类型中有一个带有通配符的变量,则只要需要在代码中引用该类型,就可以使用泛型帮助器方法。您可以将代码重构为:

public class ExampleClass {

    public static final Class<?>[] classes = new Class[]{MyClass1.class,
        MyClass2.class, MyClass3.class, MyClass4.class, MyClass5.class};

    public void myMethod() {
        for (Class<?> c : DataBaseConfigUtils.classes ) {
            act(c);    
        }
    }

    private <T> void act(Class<T> c) {
        MyObjectDAO<T, Integer> myObjectDAO = getMyObjectDAO(c);
        ArrayList<T> list = myObjectDAO.queryAll();
        for (T element : list) {
            processElement(element);
        }
    }

    public <T> MyObjectDAO<T, Integer> getMyObjectDAO(Class<T> c) {
        return doSomething(c);
    }
}
通常的解决方法是将helper方法的一个参数设置为
对象,因为可以这样做

if (clazz == String.class) { //do something }
(请注意,如果
T
本身是泛型类型,这将不起作用,因为您无法编写
List.class
。例如,有一种称为超级类型标记的解决方法。)

由于您使用的对象是
对象,因此类型擦除不会给您带来任何问题。

例如:

ParameterizedType superclass = (ParameterizedType)getClass().getGenericSuperclass();
    this.entityClass = (Class<T>) superclass.getActualTypeArguments()[0];
使用BaseEntity创建基本dao,它将返回一些扩展到实体的实体:

public class AbstarctDAO<T extends ABaseEntity, PK extends Serializable>  {

@PersistenceContext
protected EntityManager em;
protected Class<T> entityClass;

protected AbstarctDAO() {

}
@PostConstruct
public void init(){
    final ParameterizedType superclass = (ParameterizedType)getClass().getGenericSuperclass();
    this.entityClass = (Class<T>) superclass.getActualTypeArguments()[0];

}
    @Override
    public T create(T object) throws Exception {
        em.persist(object);
        em.flush();
        return object;
    }
...
}
公共类Abstractdao{
@持久上下文
受保护的实体管理器em;
保护类实体类;
受保护的AbstractDao(){
}
@施工后
公共void init(){
最终参数化类型超类=(参数化类型)getClass().getGenericSuperclass();
this.entityClass=(类)超类.getActualTypeArguments()[0];
}
@凌驾
公共T创建(T对象)引发异常{
em.persist(object);
em.flush();
返回对象;
}
...
}
执行示例: 一,

Abstractdao dao=新的Abstractdao();
试一试{
创建(新的子对象());
}捕获(例外e){
}
2.
@无国籍
@交易的
公共类ChildDAO扩展了AbstractDAO{
@事务性(Transactional.TxType.SUPPORTS)
公共子getChildByName(字符串名称){
...
return(Child)query.getSingleResult();
}
}

OP不需要该类型在运行时可用。他只想引用代码中的类型,这是可能的。
public abstract class ABaseEntity{
...
}
public class Child extends ABaseEntity{
...
}
public class AbstarctDAO<T extends ABaseEntity, PK extends Serializable>  {

@PersistenceContext
protected EntityManager em;
protected Class<T> entityClass;

protected AbstarctDAO() {

}
@PostConstruct
public void init(){
    final ParameterizedType superclass = (ParameterizedType)getClass().getGenericSuperclass();
    this.entityClass = (Class<T>) superclass.getActualTypeArguments()[0];

}
    @Override
    public T create(T object) throws Exception {
        em.persist(object);
        em.flush();
        return object;
    }
...
}
 AbstarctDAO dao = new AbstarctDAO();
        try {
            dao.create(new Child ());
        }catch (Exception e){

        }
 2.
@ Stateless
@ Transactional
public class ChildDAO extends AbstarctDAO<Child , Long> {
    @Transactional(Transactional.TxType.SUPPORTS)
    public Child getChildByName(String name) {
        ...
        return (Child)query.getSingleResult();
    }

}