Note that unlike a bounded type variable, a bounded wildcard can have only a single boundeither an upper
bound or a lower bound. For example, if you would like to restrict the type of list to be one containing
elements that are at least of class Value and also implement Serializable, you cannot say
List<?extendsValue&Serializable>.
Of course, you can also have an unbounded wildcard. For example, List<?> represents a list of any
kindimplicitly the upper bound is Object. But remember that List<?> is not another way of saying
List
In contrast to the non-wildcard versions, parameterized types that include a bounded wildcard are related in
the way you might have expected. For example,List<?extendsInteger> is a subtype of
List<?extendsNumber>, which is itself a subtype of List<?>. Similarly, List<?superNumber>
is a subtype of List<?superInteger>. In addition, non-wildcard parameterized types are subtypes of
suitably bounded, wildcard parameterized types. For example, List
List<?extendsNumber>, as is List
difference between the behavior with and without bounded wildcards can be a source of confusion. Perhaps
the following diagram will clarify things:
These properties of wildcards make them not only useful but essential for effective use of generic types.
Whenever a method takes a parameter that is a parameterized type or returns a parameterized type, that
parameterized type should almost always be expressed with a wildcard of some form. Typically, parameters
use lower-bounded wildcards, while return values use upper bounded wildcardsthough if there is a constraint
between a parameter type and the return type, it may not be possible to use a wildcard. Even a type bound that
is a parameterized type will often be expressed with a wildcard. Recall the example of the
SortedCollection
Comparable
each other. In fact, this constraint is overly tightfor two elements of a class T to be comparable to each other,
it is not necessary that T extend Comparable where S is T or
any supertype of T. For example, if class Value implements Comparable
interface SortedCollection<E extends Comparable<? super E>> {
// ... sorted collection methods ...
}
Wildcards are essential for obtaining the flexibility that we needed in the sum example, but they have a
limitation: Because the wildcard represents 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]