Легче всего осознать эти понятия на примерах:
- Ковариантность:
List<Integer>можно присвоить в переменную типаList<? extends Number>(как будто он наследникList<Number>). - Контравариантность: в качестве параметра метода
List<Number>#sortтипаComparator<? super Number>может быть переданComparator<Object>(как будто он родительComparator<Number>).
Существует еще одно связанное понятие – инвариантность. Инвариантность – это отсутствие свойств ковариантности и контрвариантности. Дженерики без вайлдкардов инвариантны:
List<Number> нельзя положить ни в переменную типа List<Double>, ни в List<Object>.Массивы ковариантны: в переменную
Object[] можно присвоить значение типа String[].Переопределение методов начиная с Java 5 ковариантно относительно типа результата и типов исключений.
