У мене, здається, є непорозуміння щодо різниці між <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)
Виходячи з мого теперішнього розуміння, я бачу, чому я не можу додати Foo
список до списку <? extends Foo>
, оскільки він не є самим підкласом; але мені цікаво, чому я не можу додати Bar
до списку.
Де дірка в моєму розумінні?
<? extends Foo>
це специфічний і невідомий клас, який розширюється Foo
. Операція з цим класом є законною лише в тому випадку, якщо вона була б законною для будь-якого підкласу Foo
.