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.
As per the Javadoc of the getClass
method:
The actual result type is
Class<? extends |X|>
where |X| is the erasure of the static type of the expression on whichgetClass
is called. For example, no cast is required in this code fragment
Here, the value for |X|
in your code snippet is MyClass
, hence instance.getClass()
is assignable to only Class<? extends MyClass>
or Class<?>
.
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 extend MyClass
and hence capable of satisfying the T extends MyClass
criteria. Without runtime information there is no way of knowing which concrete implementation subclass of MyClass
was passed in the method. Hence to provide a generic solution, it returns <? extends MyClass>
since that would hold true for any subclass of MyClass
irrespective of what class instance is passed in.
Java does not support a generic type of <this> e.g.
Object could implement
class Object {
Class<this> getClass()
}
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.
java.lang.Class
does not represent a type (use java.lang.reflect.Type
for that). If T
, were say ArrayList<String>
then it makes no sense for there to be a Class<ArrayList<String>>
.
It's worth noting that in this particular case there is no need for the method to be generic.
public static <T extends MyClass> void myMethod(T instance) {
Is equivalent to:
public static void myMethod(MyClass instance) {
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