代码之家  ›  专栏  ›  技术社区  ›  Jaap Coomans

如何确定泛型类型的类?

  •  57
  • Jaap Coomans  · 技术社区  · 18 年前

    例子:

    public class MyGenericClass<T> {
      public void doSomething() {
        // Snip...
        // Call to a 3rd party lib
        T bean = (T)someObject.create(T.class);
        // Snip...
      }
    }
    

    显然,上面的示例不起作用,并导致以下错误:类型参数t的非法类文本。

    我的问题是:有人知道一个好的替代方案或解决方法吗?

    7 回复  |  直到 18 年前
        1
  •  49
  •   Nicolas    16 年前

    仍然存在同样的问题:通用信息在运行时被删除,无法恢复。解决方法是在静态方法的参数中传递类T:

    public class MyGenericClass<T> {
    
        private final Class<T> clazz;
    
        public static <U> MyGenericClass<U> createMyGeneric(Class<U> clazz) {
            return new MyGenericClass<U>(clazz);
        }
    
        protected MyGenericClass(Class<T> clazz) {
            this.clazz = clazz;
        }
    
        public void doSomething() {
            T instance = clazz.newInstance();
        }
    }
    

    虽然很难看,但它很管用。

        2
  •  22
  •   Radiodef    11 年前

    我刚才提到了这个解决方案:

    import java.lang.reflect.ParameterizedType;
    
    public abstract class A<B> {
        public Class<B> g() throws Exception {
            ParameterizedType superclass =
                (ParameterizedType) getClass().getGenericSuperclass();
    
            return (Class<B>) superclass.getActualTypeArguments()[0];
        }
    }
    

    如果 A 由子类指定具体类型:

    new A<String>() {}.g() // this will work
    
    class B extends A<String> {}
    new B().g() // this will work
    
    class C<T> extends A<T> {}
    new C<String>().g() // this will NOT work
    
        3
  •  4
  •   Steven Collins Sungwon Jeong    10 年前

    不幸的是,Christoph的书面解决方案只在非常有限的情况下有效。[编辑:正如下面评论的那样,我已经记不起我对这句话的推理了,它很可能是错误的:“注意,这首先只适用于抽象类。”]下一个困难是 g() 仅适用于的直接子类 A . 不过,我们可以解决这个问题:

    private Class<?> extractClassFromType(Type t) throws ClassCastException {
        if (t instanceof Class<?>) {
            return (Class<?>)t;
        }
        return (Class<?>)((ParameterizedType)t).getRawType();
    }
    
    public Class<B> g() throws ClassCastException {
        Class<?> superClass = getClass(); // initial value
        Type superType;
        do {
            superType = superClass.getGenericSuperclass();
            superClass = extractClassFromType(superType);
        } while (! (superClass.equals(A.class)));
    
        Type actualArg = ((ParameterizedType)superType).getActualTypeArguments()[0];
        return (Class<B>)extractClassFromType(actualArg);
    }
    

    public class Foo<U,T extends Collection<?>> extends A<T> {}
    
    (new Foo<String,List<Object>>() {}).g();
    

    这将抛出一个 ClassCastException ,因为这里的类型参数不是 Class ParameterizedType 完全这是最重要的 TypeVariable T . 所以,现在你将被困在试图找出什么类型 应该是代表,等等,在兔子洞下面。

        4
  •  2
  •   Jet Geng    15 年前

    我找到了获取泛型对象类的另一种方法

    public Class<?> getGenericClass(){
             Class<?> result =null;
             Type type =this.getClass().getGenericSuperclass();
    
             if(type instanceofParameterizedType){
                  ParameterizedType pt =(ParameterizedType) type;
                  Type[] fieldArgTypes = pt.getActualTypeArguments();
                  result =(Class<?>) fieldArgTypes[0];
            }
            return result;
      }
    
        5
  •  0
  •   intrepidis    12 年前

    我将详细阐述克里斯托夫的解决方案。

    下面是ClassGetter抽象类:

    private abstract class ClassGetter<T> {
        public final Class<T> get() {
            final ParameterizedType superclass = (ParameterizedType)
                getClass().getGenericSuperclass();
            return (Class<T>)superclass.getActualTypeArguments()[0];
        }
    }
    

    下面是一个静态方法,它使用上述类查找泛型类的类型:

    public static <T> Class<T> getGenericClass() {
        return new ClassGetter<T>() {}.get();
    }
    

    public static final <T> T instantiate() {
        final Class<T> clazz = getGenericClass();
        try {
            return clazz.getConstructor((Class[])null).newInstance(null);
        } catch (Exception e) {
            return null;
        }
    }
    

    T var = instantiate();
    
        6
  •  0
  •   Radiodef    11 年前

    使用 TypeTools

    Class<T> t = (Class<T>) TypeResolver.resolveRawArguments(
                                    MyGenericClass.class, getClass());
    
        7
  •  -1
  •   Abul Kasim M    8 年前

    公共类数据库accessutil{

    EntityManagerFactory entitymanagerfactory;
    EntityManager entitymanager;
    
    public DatabaseAccessUtil() {
        entitymanagerfactory=Persistence.createEntityManagerFactory("bookmyshow");
        entitymanager=entitymanagerfactory.createEntityManager();
    }
    
    public void save  (T t) {
        entitymanager.getTransaction().begin();
        entitymanager.persist(t);
        entitymanager.getTransaction().commit();
    }
    
    public void update(T t) {
        entitymanager.getTransaction().begin();
        entitymanager.persist(t);
        entitymanager.getTransaction().commit();
    }
    
    public void delete(T t) {
        entitymanager.getTransaction().begin();
        entitymanager.remove(t);
        entitymanager.getTransaction().commit();
    }
    
    public Object retrieve(Query query) {
        return query.getSingleResult();
    }
    //call the method - retrieve(object,requiredclass.class)
    public Object retrieve(Object primaryKey,class clazz) throws Exception {
    
        return entitymanager.find(clazz,primaryKey);    
    
    }