Java Reference
In-Depth Information
ideal world in which everyone used generics, such casts would simply
be disallowed (as is use of
instanceof
). Some degree of interoperability
between generic code and non-generic code must be provided, so the
casts are allowed but are replaced by casts to the erasure of the type
variable or parameterized type, usually causing the compiler to emit an
"unchecked" warning
(see page
745
). This warns you that the cast can
neither be checked at runtime nor guaranteed to be type-safe at com-
pile time. For example, a method with a
SingleLinkQueue<?>
paramet-
er could cast it to
SingleLinkQueue<String>
and add a
String
. This would
cause the compiler to emit an "unchecked" warning. At runtime, the ac-
tual cast to
SingleLinkQueue
would succeed even if the queue was actually
of type
SingleLinkQueue<Number>
, and the
String
would be added, violating
the type integrity of the queue. This violation would only be detected
when a
remove
invocation tried to cast the returned instance to
Number
,
resulting in a runtime
ClassCastException
. Note, however, that if the cast
does not involve a change to the type parameter, then the cast is quite
safe and there is no warning. For example, a cast from
Collection<T>
to
List<T>
doesn't require checking anything about
T
.
Casts involving parameterized types are unavoidable in many circum-
stances, such as when a method returns a (possibly non-generic) super-
type, and the actual object will be of a generic subtype that you need to
cast to that subtype. In such circumstances you should use casts that
only involve unbounded wildcards, and assign the results to variables
that also declare unbounded wildcards. The fact that you need a cast
means that you have lost valuable type information and there is no way
to restore that information at runtime, so casting to a parameterized
type should always involve unbounded wildcards. For example, consider
a non-generic version of the
passThrough
method:
Object passThrough(Object o) {
return o;
}
and its subsequent use with an instance of
List<String>
: