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
}
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.
getGenericSuperclass() - as there is no inheritance involved in this simple case.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 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.
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).
When you have a question like this, you should ask yourself, how would you do it without Generics? Because any Generics program can be converted into an equivalent program without Generics. (This conversion is called type erasure.) So if you cannot do it without Generics, you cannot do it with Generics either.
Your program without Generics looks like this:
public static class MyClass {
ArrayList mArrayList = new ArrayList();
}
@Test
public final void test() {
MyClass myObject = new MyClass();
Integer result = getParamType( myObject ); // how would you implement getParamType()?
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With