Jean-Philippe Pellet
Jean-Philippe Pellet

Reputation: 60006

Casting to generic subtypes of a generic class

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

Answers (1)

Paul Bellora
Paul Bellora

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

Related Questions