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.
- 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.
.
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.)
>() {}.getType()` i can get `java.util.List` (but this is not useful, as it is not getting from the object). Then i let `class MyClass extends TypeReference` and by `myObject.getType()` i get only `T`. Thanks for guided me the way. Please help me to go a bit further.
– midnite Aug 20 '13 at 16:24