简单地说:
public static class MyClass< T> { //如果没有必要,我不想保留T的一个实例。 //它不好,不整齐。 //或者,假设成员的形式如下: ArrayList< T> mArrayList = new ArrayList< T>(); //获取泛型类型参数的问题仍然存在。 } @Test public final void test(){ MyClass< Integer> myObject = new MyClass< Integer>(); getParamType(myObject); } private static final< T> void getParamType(final MyClass< T> _myObject){ System.out.println(_myObject.getClass()。getTypeParameters()[0]); ()(T)new Object())。getClass()); // T System.out.println // class java.lang.Object }如何让代码打印类java.lang.Integer ?
我知道很多stackoverflow线程正在询问(和回答)这个问题。但是他们无法解决这个问题。
- 我不知道为什么有些人需要调用 getGenericSuperclass() - 因为在这个简单情况下没有继承。
- 我不能将它转换为 ParameterizedType $ c $ $ b $ p $ $ c> System.out.println((ParameterizedType)_myObject.getClass()); //编译错误:无法从Class< capture#11-of?扩展TreeTest2.MyClass> to ParameterizedType System.out.println((ParameterizedType)_myObject.getClass()。getGenericSuperclass()); //运行时异常:java.lang.ClassCastException
- i don't know why some need to call getGenericSuperclass() - as there is no inheritance involved in this simple case.
- And i can't cast it to ParameterizedType as well.
基于@ Thomas的指导,我发现了一种 解决方法 来获取类java.lang.Integer $ c首先,我们创建匿名(它需要是匿名的)子类 MyClass< code
; T> 在测试代码中。 (这很奇怪,为什么它只支持子类?)
@Test public final void test() { MyClass< Integer> myObject = new MyClass< Integer>(){}; //匿名子类 getParamType(myObject); $ / code>然后我们可以使用 getGenericSuperclass() code>方法来获取类型然后将其转换为 ParameterizedType ,之后使用 getActualTypeArguments():
private static final< T> void getParamType(final MyClass< T> _myObject){ System.out.println(((ParameterizedType)_myObject.getClass()。getGenericSuperclass())。getActualTypeArguments()[0]); }完美地打印类java.lang.Integer 。
这是不太好,因为测试代码应该模拟实际情况,用户最有可能将不会继续创建无意义的子类。这种方法基于 TypeReference类。但我真的不知道如何使用它。我试过 class MyClass< T>扩展了TypeReference< T> 。但我仍然需要创建 MyClass< T> 的子类以使 TypeReference.getType()打印 class java.lang.Integer 。
请帮忙,谢谢任何输入,因为最好的方法还没有出现。 基于上述解决方法的进一步问题:为什么只有匿名子类有效?
public static class SubMyClass< T>扩展MyClass< T> {} @Test public final void test(){ MyClass< Integer> myObject = new MyClass< Integer>(){}; //匿名子类 getParamType(myObject); // class java.lang.Integer MyClass< Integer> mySubObject = new SubMyClass< Integer>(); //命名的子类 getParamType(mySubObject); // T( MyClass 和 getParamType()不变。)
解决方案因为Java故意无法做到这一点(类型擦除)。
解决方法称为超级类型令牌。还有一些关于此的线索(如这一个或那一个)。
Simply:
public static class MyClass<T> { // i don't want to keep an instance of T, if it is not necessary. // and it is not nice, not neat. // Or, let's say, the member are in the form of : ArrayList<T> mArrayList = new ArrayList<T>(); // the problem of getting the generic type parameter is still present. } @Test public final void test() { MyClass<Integer> myObject = new MyClass<Integer>(); getParamType( myObject ); } private static final <T> void getParamType(final MyClass<T> _myObject) { System.out.println(_myObject.getClass().getTypeParameters()[0]); // T System.out.println(((T) new Object()).getClass()); // class java.lang.Object }How to let the code print class java.lang.Integer?
i know quite a few of stackoverflow threads are asking (and answering) about this. Yet they couldn't solve this question.
.
System.out.println((ParameterizedType) _myObject.getClass()); // Compile Error: Cannot cast from Class<capture#11-of ? extends TreeTest2.MyClass> to ParameterizedType System.out.println((ParameterizedType) _myObject.getClass().getGenericSuperclass()); // Runtime Exception: java.lang.ClassCastException
Based on @Thomas's guide, i have found a work-around way to get class java.lang.Integer.
First, we create an anonymous (it need to be anonymous) sub-class of MyClass<T> in the testing code. (Which is weird. Why it only support sub-classes?)
@Test public final void test() { MyClass<Integer> myObject = new MyClass<Integer>() {}; // Anonymous sub-class getParamType( myObject ); }Then we can use the getGenericSuperclass() method to get a Type then cast it to ParameterizedType and afterwards uses getActualTypeArguments():
private static final <T> void getParamType(final MyClass<T> _myObject) { System.out.println( ((ParameterizedType) _myObject.getClass().getGenericSuperclass()).getActualTypeArguments()[0] ); }It perfectly prints class java.lang.Integer.
This is not-so-good because the testing codes should simulate the actual situation, where users most likely won't keep creating meaningless sub-classes.This approach is based on the idea of the TypeReference class. But i don't really know how to use it. I have tried class MyClass<T> extends TypeReference<T>. But i still have to create sub-class of MyClass<T> to have TypeReference.getType() prints class java.lang.Integer.
Please help, and thanks for any inputs, as the best approach is not here yet.
A further question based on the above workaround: Why only anonymous sub-class works? public static class SubMyClass<T> extends MyClass<T>{} @Test public final void test() { MyClass<Integer> myObject = new MyClass<Integer>() {}; // Anonymous sub-class getParamType( myObject ); // class java.lang.Integer MyClass<Integer> mySubObject = new SubMyClass<Integer>(); // named sub-class getParamType( mySubObject ); // T }(MyClass and getParamType() unchanged.)
解决方案This is sort of difficult, because Java deliberately can't do that ("type erasure").
The work-around is called super type tokens. There are also some threads on SO about that (like this one or that one).
更多推荐
如何获得通用类型参数?
发布评论