Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 202
Jean-Philippe Pellet Avatar asked Jul 26 '13 14:07

Jean-Philippe Pellet


People also ask

What is generic type casting?

In the general case, a generic type could be both a supplier and a consumer of its type parameters, which means that the type we get by casting the type parameter (up or down) cannot be either a subtype or a supertype of the original: they are unrelated types that cannot be cast between, which is exactly why the Java ...

Does generics eliminate the use of casting?

As mentioned previously, generics can eliminate the requirement for casting.

What are generic methods generic methods are the methods defined in a generic class?

Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.

Can a generic class be subclass of non generic?

Yes you can do it.


Video Answer


1 Answers

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>.

like image 109
Paul Bellora Avatar answered Sep 17 '22 10:09

Paul Bellora