Ответ 1
listOne.add(abcdef)
(строка 1) недействительна, поскольку List<?>
представляет список неизвестного определенного типа. Например, это может быть List<String>
, поэтому мы не хотим добавлять ничего, что не является String
. Ошибка компилятора происходит потому, что Abc<Def<Ghi<String>>>
не присваивается ?
.
listTwo.add(abcdef)
(строка 2) действительна, поскольку List<Abc<?>>
представляет список Abc
любого типа. Эти правые вложенные подстановочные знаки отличаются от подстановочных знаков верхнего уровня тем, что они представляют собой любой тип, а не определенный тип (другими словами, вложенные подстановочные знаки не capture). Компилятор допускает это, потому что Abc<Def<Ghi<String>>>
можно присваивать Abc<?>
. См. Это сообщение для дальнейшего обсуждения вложенных подстановочных знаков: Множественные подстановочные знаки для общих методов делают Java-компилятор (и меня!) Очень запутанным
listThree.add(abcdef)
(строка 3) недействительна, поскольку List<Abc<Def<?>>>
представляет список Abc
of Def
любого типа. Дженерики не ковариантны, поэтому Abc<Def<Ghi<String>>>
не присваивается Abc<Def<?>>
, хотя Def<Ghi<String>>
присваивается Def<?>
. A List<Integer>
по той же причине не присваивается a List<Number>
. См. Это сообщение для дальнейшего объяснения: Is List <Dog> подкласс списка <Animal> ? Почему неспецифические полиморфины Java неявно?
listFour.add(abcdef)
(строка 4) недействительна по той же причине - Abc<Def<Ghi<String>>>
не присваивается Abc<Def<Ghi<?>>>
.
listFive.add(abcdef)
(строка 5) действительна, потому что общие типы точно соответствуют - Abc<Def<Ghi<String>>>
, очевидно, присваивается Abc<Def<Ghi<String>>>
.