I have a list like that:
private List<T> myList = new ArrayList<T>();
I want to get the .class of T. How can I do that?
I mean as like:
myList.getClass()
EDIT:
I tried that:
Field genericField = Wrapper.class.getDeclaredField("myList");
ParameterizedType genericType = (ParameterizedType) genericField.getGenericType();
Class<?> genericClass = (Class<?>) genericType.getActualTypeArguments()[0];
and when I debug it
genericType
has a value of:
java.util.List
so I think that this is certainly different issue from that question: Get generic type of java.util.List because of if you declare a class with T
and assign something to T
later at another method, class that T
holds disappear.
You can't because of type erasure.
The generic type is not known at runtime (it's 'erased'), it's only used at compile time.
This is a major difference between java generics and c# generics for example.
Why do you need to know this? Perhaps this will do what you need
// must be at least one element (and all elements are the same)
Class elementType = myList.get(0).getClass();
The only way to do this is to either
- store the type in a field and add a getter method for this.
like
private final Class<T> type;
private final List<T> list = new ArrayList<T>();
public Class<T> getType() { return type; }
- use getGenericType() on the actual field, assuming the parameter type is NOT generic.
- use a sub class with a specific type.
like
List list = new ArrayList<Integer>() { }; // create a specific sub-class
final Class<? extends List> listClass = list.getClass();
final ParameterizedType genericSuperclass = (ParameterizedType) listClass.getGenericSuperclass();
Class elementType = (Class) genericSuperclass.getActualTypeArguments()[0];
This has the dis-advantage that you could end up creating lots of anonymous classes and potential confusion with things like ArrayList.class != list.getClass()
however list instanceof ArrayList
You cannot. That information is not available at runtime. If your list isn't empty you might be able to get away with checking the class of the first element.
This is only possible if the list, as implied in your example, is a field AND the type parameter is concrete rather than itself being a type parameter of the enclosing class (which seems to be the case in your example), and you can only get the declared type parameter for the field via reflection:
Field listField = Test.class.getDeclaredField("myList");
ParameterizedType listType= (ParameterizedType) listField.getGenericType();
Class contentClass = (Class) listType.getActualTypeArguments()[0];
Not sure if this is entirely correct, but you get the idea - it's rather complex because type parameters can be bounded and wildcards.