如何确定一个generics的类?

我正在创build一个generics类,在我需要知道当前正在使用的generics类的一个方法。 原因在于我所称的方法之一就是期待这个论点。

例:

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

显然,上面的例子不起作用,导致以下错误:types参数T的非法类文字。

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

仍然是同样的问题:通用信息在运行时被擦除,它不能被恢复。 一个解决方法是在一个静态方法的参数中传递类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(); } } 

这是丑陋的,但它的作品。

我只是指出了这个解决scheme:

 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通过子类给出具体types,这是有效的:

 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 

不幸的是,Christoph的解决scheme只能在非常有限的情况下使用。 [编辑:作为下面的评论我不再记得我的推理这个句子,它可能是错误的:“注意,这将只能在抽象类,首先。”]下一个困难是, 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 ,因为这里的types参数根本不是一个Class或一个ParameterizedType ; 这是TypeVariable T 所以现在你会被卡住试图弄清楚T应该代表什么types,等等。

我认为唯一合理的,一般的答案类似于Nicolas的初始答案 – 一般来说,如果你的类需要在编译时实例化其他一些未知类的对象,那么你的类的用户需要传递这个类的文字(或者也许是一个工厂),而不是仅仅依靠generics。

我find另一种方法来获得通用对象的类

 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; } 

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

这里是ClassGetter抽象类:

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

这是一个静态的方法,它使用上面的类来find一个generics类的types:

 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(); 

T可以使用TypeTools很容易地解决:

 Class<T> t = (Class<T>) TypeResolver.resolveRawArguments( MyGenericClass.class, getClass());