Кажется, у меня неправильное понимание разницы между <Foo>
и <? extends Foo>
. Из моего понимания, если бы мы имели
ArrayList<Foo> foos = new ArrayList<>();
Это указывает на то, что объекты этого типа Foo
могут быть добавлены в этот список массивов. Поскольку подклассы Foo
также имеют тип Foo
, они также могут быть добавлены без ошибок, как показано
ArrayList<Foo> foos = new ArrayList<>();
foos.add(new Foo());
foos.add(new Bar());
где Bar extends Foo
.
Теперь, скажем, я определил foos
как
ArrayList<? extends Foo> foos = new ArrayList<>();
Мое текущее понимание состоит в том, что это выражает some unknown type that extends Foo
. Я понимаю, что это означает, что любые объекты, которые являются подклассом, Foo
могут быть добавлены в этот список; Это означает, что нет разницы между ArrayList<Foo>
и ArrayList<? extends Foo>
.
Чтобы проверить это, я попытался написать следующий код
ArrayList<? extends Foo> subFoos = new ArrayList<>();
subFoos.add(new Foo());
subFoos.add(new Bar());
но было предложено со следующей ошибкой компиляции
no suitable method found for add(Foo)
method java.util.Collection.add(capture#1 of ? extends Foo) is not applicable
(argument mismatch; Foo cannot be converted to capture#1 of ? extends Foo)
no suitable method found for add(Bar)
method java.util.Collection.add(capture#2 of ? extends Bar) is not applicable
(argument mismatch; Bar cannot be converted to capture#2 of ? extends Bar)
Исходя из моего нынешнего понимания, я понимаю, почему я не могу добавить a Foo
в список <? extends Foo>
, потому что он не является подклассом сам по себе; но мне любопытно, почему я не могу добавить Bar
в список.
Где дыра в моем понимании?
<? extends Foo>
является конкретным и неизвестным классом, который расширяетсяFoo
. Операция с этим классом допустима только в том случае, если она допустима для любого подклассаFoo
.Ответы:
Как вы обнаружили сами,
ArrayList
заявленное какArrayList<? extends Foo> subFoos = new ArrayList<>();
не будет очень полезным.Чтобы увидеть полезность
<? extends T>
рассмотрим это:который позже можно использовать следующим образом:
или следующим образом:
обратите внимание, что ничего из вышеперечисленного не сработало бы, если бы
collect
метод был объявлен следующим образом:источник