Подтвердить что ты не робот

Java generics, вложенный набор подстановочных знаков

Это компилирует (1.6)

List<? extends Object> l = new ArrayList<Date>();

Но это не

List<List<? extends Object>> ll = new ArrayList<List<Date>>();

с ошибкой

Type mismatch: cannot convert from ArrayList<List<Date>> to List<List<? extends Object>>

Может кто-нибудь объяснить, почему? Благодаря

EDIT: отредактирован для последующего

4b9b3361

Ответ 1

Потому что это нарушит безопасность типа:

List<List<Object>> lo = new ArrayList<List<Object>>();
List<List<? extends Object>> ll = lo;
List<String> ls = new ArrayList<String>();
ll.add(ls);
lo.get(0).add(new Object());
String s = ls.get(0); // assigns a plain Object instance to a String reference

Ответ 2

Хорошо объяснения верны, но я думаю, было бы неплохо добавить и фактическое рабочее решение;)

List<? extends List<? extends Object>>

Будет работать отлично, но, очевидно, использование такой коллекции довольно ограничено обычными ограничениями общих коллекций (но тогда то же самое верно для более простой List <? extends Date > )

Ответ 3

Предположим, что D является подтипом B, G<T> является общим типом

B x = new D(); // OK

G<B> y = new G<D>(); // FAIL

Теперь G<Date> является подтипом G<?>, поэтому

G<?> x = new G<Date>();  // OK

G<G<?>> y = new G<G<Date>>(); // FAIL

Ответ 4

<? extends Object>  

означает, что подстановочный знак может быть заменен только для тех объектов, которые являются подклассом класса Object.

List<List<? extends Object>> ll = new ArrayList<List<Object>>();  

дает вам ошибку несоответствия типов, потому что вы пытаетесь назначить ArrayList из списка объектов класса java Object на List, который содержит List любого типа объектов, которые являются подклассом java класс Object.

Для получения дополнительной информации см. Подстановочная документация

Ответ 5

При назначении переменной (List<T>) с несимвольным общим типом T назначаемый объект должен иметь ровно T как свой общий тип (включая все параметры типового типа T, подстановочный знак и несимвольный). В вашем случае T есть List<? extends Object>, который не совпадает с типом List<Date>.

Что вы можете сделать, потому что List<Date> присваивается List<? extends Object>, используется тип подстановочного знака:

List<? extends List<? extends Object>> a = new ArrayList<List<Date>>();