These concepts are best understood through examples:
- Covariance: A
List<Integer>can be assigned to a variable of typeList<? extends Number>(as if it were a subtype ofList<Number>). - Contravariance: A
Comparator<Object>can be passed as a parameter to a methodList<Number>#sortthat expects aComparator<? super Number>, as if it were a supertype ofComparator<Number>.
There's also a related concept called invariance, which is the absence of covariance and contravariance properties. Generics without wildcards are invariant:
List<Number> cannot be assigned to a variable of type List<Double> or List<Object>.Arrays in Java are covariant: a
String[] value can be assigned to a variable of type Object[].Since Java 5, method overriding is covariant with respect to the return type and the types of exceptions.
