The unknown type sometimes confuses developers—provoking questions like,
“Why wouldn't you just use Object instead of the unknown type?” However, as
we've seen, the need to have subtyping relationships between generic types essen‐
tially requires us to have a notion of the unknown type.
In fact, Java's wildcard types extend beyond just the unknown type, with the concept
of bounded wildcards , also called type parameter constraints . This is the ability to
restrict the types that can be used as the value of a type parameter.
They are used to describe the inheritance hierarchy of a mostly unknown type—
effectively making statements like, for example, “I don't know anything about this
type, except that it must implement List .” This would be written as ? extends
List in the type parameter. This provides a useful lifeline to the programmer—
instead of being restricted to the totally unknown type, she knows that at least the
capabilities of the type bound are available.
The extends keyword is always used, regardless of whether
the constraining type is a class or interface type.
This is an example of a concept called type variance , which is the general theory of
how inheritance between container types relates to the inheritance of their payload
This means that the container types have the same relationship to each other as
the payload types do. This is expressed using the extends keyword.
This means that the container types have the inverse relationship to each other
as the payload types. This is expressed using the super keyword.
These principles tend to appear when discussing container types that act as produc‐
ers or consumers of types. For example, if Cat extends Pet , then List<Cat> is a sub‐
type of List<? extends Pet> . The List is acting as a producer of Cat objects and
the appropriate keyword is extends .
For a container type that is acting purely as a consumer of instances of a type, we
would use the super keyword.