In such a function:
void foo(T obj)
The type of obj.getClass()
is Class>
and not Class<
In Java generics are just a source level tool for safer development.
The JVM does not know anything about generics. The Java compiler throws away this information, and all generic types are indeed just Object references at runtime. To compensate for that the compiler inserts the necessary casts. This procedure is called Type Erasure (Google!).
List<String> x = new ArrayList<String>();
x.add("hello");
String hello = x.get(0);
becomes the following at runtime
List x = new ArrayList();
x.add("hello");
String hello = (String) x.get(0);
To solve your problem you could try to investigate the individual elements in your array (arr[0].getClass()
).
There are a couple of not totally accurate answers here. Generics are indeed implemented using type erasure, however this does not mean that all type information is lost. The compiler will erase the type to the lowest bound it can.
So <T extends String> gets erased to String; this is why getClass on a String returns Class<? extends String>. Your unbounded <T> however gets erased to Object; and so getClass returns Class<? extends Object>, i.e. Class<?>
Generics are complex, and they don't always do what you want, but there are ways to work around many things (by improving your bounds, accessing runtime type information via reflection, and passing class objects around). Type erasure is actually a pretty clever solution, undeserving of much of the bad press it has received.
Because of type erasure, the runtime doesn't keep type information for generic arrays. In effect, the JVM internally treats all generic arrays as if they are an Object[].
If you want to get a runtime type, your best option may simply be to call getClass() on the first item in the array. You'll obviously need to find a way to handle the empty case, and the case where the contained objects are of multiple types, etc.
The basic problem is that getClass() doesn't return the class because its defined at the Object level. i.e. it is mearly defined as a class which extends object. They could have defined getClass() like.
Class<this> getClass() { /**/ }
but instead its
Class<?> getClass()
which means generics has no understanding of what getClass returns.