I would expect that from the aspect of compile time as well as from the aspect of runtime it wouldn't be a problem for .getClass()
to provide a correctly-typed return value.
But I must be wrong.
public class _GetClassGenerics2 {
static class MyClass {
}
public static void main(String[] args) {
MyClass myInstance = new MyClass();
// here it works
Class<? extends MyClass> type = myInstance.getClass();
myMethod(myInstance);
}
public static <T extends MyClass> void myMethod(T instance) {
Class<? extends T> type = instance.getClass();
// java.lang.RuntimeException: Uncompilable source code - incompatible types
// required: java.lang.Class<? extends T>
// found: java.lang.Class<capture#1 of ? extends _GetClassGenerics2.MyClass>
}
}
EDIT: It doesn't work with Class<T>
and Class<? super T>
either.
Instead of
you need to use
You cannot directly use the
T
here.The reason is the method signature of
Object.getClass()
(which you are invoking). It's:So you are trying to convert from
Class<? extends Object>
toClass<? extends T>
, which is not allowed (because you are down-casting). It is allowed using an explicit cast:will work (though it generates a type safety warning).
As per the Javadoc of the
getClass
method:Here, the value for
|X|
in your code snippet isMyClass
, henceinstance.getClass()
is assignable to onlyClass<? extends MyClass>
orClass<?>
.The reason for this specific wording is because when you say that for this variable having type T where
<T extends MyClass>
, there can be multiple classes which extendMyClass
and hence capable of satisfying theT extends MyClass
criteria. Without runtime information there is no way of knowing which concrete implementation subclass ofMyClass
was passed in the method. Hence to provide a generic solution, it returns<? extends MyClass>
since that would hold true for any subclass ofMyClass
irrespective of what class instance is passed in.java.lang.Class
does not represent a type (usejava.lang.reflect.Type
for that). IfT
, were sayArrayList<String>
then it makes no sense for there to be aClass<ArrayList<String>>
.It's worth noting that in this particular case there is no need for the method to be generic.
Is equivalent to:
Java does not support a generic type of <this> e.g.
Object could implement
But there is no way for getClass() to express that it will return a type which is the class of the object. The compiler has no native understand of what this method does either.
IMHO, This behaviour should have been supported.