There is a difference between type parameters and type arguments. The use of wildcards (super
and extends
) is for type arguments, that is, you declare them at the call site when you're actually defining the corresponding value of a type parameter. Alternatively, the keyword extends
can be used for type parameter constraints.
Type Parameters vs Type Arguments
As such, in the definition class List<T>{}
, T
is called a type parameter. Whe you a declare a reference of type List
, at the call site you are allowed to provide a type argument for T
, which can be an invariant (i.e. List<String> jedis
) or a wildcard with super or with extends (i.e. List<? extends Number> myNums
, List<? super String> names
).
Type Parameter Constraints
The keyword extends
can also be used in a totally different purpose to declare constraints for a given type parameter. For instance, the declaration:
class List<T extends CharSequence>{}
The type parameter T
is constrained. This would imply that whenever you declare a type argument for your type parameter T
, it must be of type CharSequence
or any of its subtypes.
As such List<String>
would be valid declaration, but List<Integer>
would not.
The use of the keyword super
is not allowed in the declaration of type parameter constraints, probably because it does not make a lot of sense, in your declaration, what could be a valid type argument for T
that is not A
itself?