Java Reference
In-Depth Information
Wildcards are essential for obtaining the flexibility that we needed in the
sum
example, but they have a limitation: Because the wildcard repres-
ents an unknown type, you can't do anything that requires the type to
be known. For example, you can't add an element to a queue referenced
through a variable that has an unbounded or upper-bounded wildcard
type:
[3]
[3]
Since the reference literal
null
has no type, the type-system will allow you to invoke
add
passing
null
, but this is an uninteresting boundary case with little practical significance.
SingleLinkQueue<?> strings =
new SingleLinkQueue<String>();
strings.add("Hello"); // INVALID: won't
compile
SingleLinkQueue<? extends Number> numbers =
new SingleLinkQueue<Number>();
numbers.add(Integer.valueOf(25)); // INVALID: won't
compile
This is a reasonable restriction because in general, if passed a queue of
an unknown kind, you have no idea what type of object you can store in
it. So you can't store a
String
(or an
Object
or a
Number
or …) in a queue
that could require some other kind of element. Nor can you store a
Num-
ber
in a queue in which the elements are known to be
Number
objects or
objects of a subclass of
Number
because in the subclass case passing a
general
Number
object would be incorrect. However, given
strings
above,
you could invoke
remove
and assign the result to an
Object
reference-
because the returned value must be compatible with
Object
. Similarly,
given
numbers
, you could invoke
remove
and assign the result to a
Number
referencebecause the returned value must be at least a
Number
.
In contrast, given a lower-bounded wildcard type, the wildcard is known
to be the same as, or a super type of, the bound, so adding an element
of the same type as the bound is always correct. For example, this
method is perfectly correct: