The following code:
public class A<T> {
Class<T> klass;
T instance;
public A(T instance) {
this.klass = instance.getClass(); // this requires an explicit cast to Class<T> to satisfy the compiler
this.instance = instance;
}
}
gives upon compilation:
A.java:7: error: incompatible types
this.klass = instance.getClass();
^
required: Class<T>
found: Class<CAP#1>
where T is a type-variable:
T extends Object declared in class A
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ? extends Object
1 error
Why isn't the compiler satisfied that instance.getClass()
will always produce Class<T>
(since instance
is of type T
) and requires an explicit cast instead? Am I safe just adding the explicit cast:
this.klass = (Class<T>) instance.getClass();
... and thus silencing the compiler or is there room for run-time surprises? And if not, why can't the compiler figure that out?
Why isn't the compiler satisfied that instance.getClass() will always produce Class (since instance is of type T) and requires an explicit cast instead?
Consider this:
A<Object> a = new A<Object>("Foo");
Calling instance.getClass()
won't return a Class<Object>
- it will return a Class<String>
. They're not the same thing, even though every String
is an Object
.
You can change the code to:
Class<? extends T> klass;
At that point it's logically safe, but it still requires a cast because Object.getClass()
is just declared to return Class<? extends |T|>
(as per JLS section 4.3.2):
The type of a method invocation expression of
getClass
isClass<? extends |T|>
whereT
is the class or interface searched (§15.12.1) forgetClass
.
The |T|
part means the type erasure of T
, which in this case is just going to be Object
.
Of course, the cast doesn't actually check anything at execution time, and you'll need @SuppressWarnings("unchecked")
to silence the compiler completely, but at least the code would make logical sense at that point.
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