В Java, если Car
является производным классом Vehicle
, тогда мы можем рассматривать все Cars
как Vehicles
; Car
- это Vehicle
. Однако List
из Cars
также не является List
из Vehicles
. Мы говорим, что List<Car>
является не ковариантным с List<Vehicle>
.
Java требует от вас явного указания, когда вы хотите использовать ковариацию и контрвариантность с подстановочными знаками, представленными маркером ?
. Посмотрите, где происходит ваша проблема:
List<List<? extends Number>> l = new ArrayList<List<Number>>();
// ---------------- ------
//
// "? extends Number" matched by "Number". Success!
Внутренний List<? extends Number>
работает, потому что Number
действительно расширяет Number
, поэтому он соответствует "? extends Number
". Все идет нормально. Что дальше?
List<List<? extends Number>> l = new ArrayList<List<Number>>();
// ---------------------- ------------
//
// "List<? extends Number>" not matched by "List<Number>". These are
// different types and covariance is not specified with a wildcard.
// Failure.
Однако объединенный параметр внутреннего типа List<? extends Number>
не соответствует List<Number>
; типы должны быть точно идентичными . Другой подстановочный знак скажет Java, что этот комбинированный тип также должен быть ковариантным:
List<? extends List<? extends Number>> l = new ArrayList<List<Number>>();