У мене, здається, є непорозуміння щодо різниці між <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.