I seem to have a misunderstanding about the difference between <Foo>
and <? extends Foo>
. From my understanding, if we had
ArrayList<Foo> foos = new ArrayList<>();
This indicates that objects of type Foo
can be added to this array list. Since subclasses of Foo
are also of type Foo
, they can also be added without an error, as illustrated by
ArrayList<Foo> foos = new ArrayList<>();
foos.add(new Foo());
foos.add(new Bar());
where Bar extends Foo
.
Now, say I had defined foos
as
ArrayList<? extends Foo> foos = new ArrayList<>();
My current understanding is that this expresses some unknown type that extends Foo
. I take this to mean that any objects that are a subclass of Foo
can be added to this list; meaning that there is no difference between ArrayList<Foo>
and ArrayList<? extends Foo>
.
To test this, I tried to write the following code
ArrayList<? extends Foo> subFoos = new ArrayList<>();
subFoos.add(new Foo());
subFoos.add(new Bar());
but was prompted with the following compilation error
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)
Based on my current understanding, I can see why I might not be able to add a Foo
to a list of <? extends Foo>
, because it is not a subclass of itself; but I am curious as to why I cannot add a Bar
to the list.
Where is the hole in my understanding?
<? extends Foo>
is a specific and unknown class that extendsFoo
. An operation with this class is legal only if it would be legal for any subclass ofFoo
.