Reputation: 60006
Suppose I have this:
class Base<T> {}
class Derived<T> extends Base<T> {}
Then in my code, I can safely cast without a warning like this:
public <T> void foo(Base<T> base) {
Derived<T> f = (Derived<T>) base; // fine, no warning
}
which is fine. But if the derived class has more type parameters, it doesn't work any more:
class Base<T> {}
class Derived<T, U> extends Base<T> {}
public <T> void foo(Base<T> base) {
Derived<T, ?> f = (Derived<T, ?>) base; // unchecked warning!
}
Why is that? Is there something obvious I'm missing here?
Upvotes: 5
Views: 347
Reputation: 55233
This seems like a bug to me. From JLS §5.5.2. Checked Casts and Unchecked Casts:
A cast from a type S to a parameterized type (§4.5) T is unchecked unless at least one of the following conditions holds:
S <: T
All of the type arguments (§4.5.1) of T are unbounded wildcards
T <: S and S has no subtype X other than T where the type arguments of X are not contained in the type arguments of T.
Given your types Base<T>
and Derived<T, ?>
as S
and T
respectively, the first two conditions clearly don't hold.
That leaves the third condition - which won't hold if we can identify a subtype of Base<T>
other than Derived<T, ?>
whose type arguments are not contained in the type arguments of Derived<T, ?>
. If the warning is correct, such a subtype must exist, but I can't identify one. For example, Derived<?, ?>
doesn't work because it isn't a subtype of Base<T>
.
Upvotes: 5