How are the Java generic extends - Foo> and different?
I seem to have a misunderstanding about the difference between
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
food.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
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?
As you have discovered by yourself, an ArrayList declared as ArrayList The Java generic extends Foo> subFoos = new ArrayList<>(); would not be very useful.
In order to see the usefulness of extends T> consider this:
List collect( List a1, List a2 )
{
List collected = new ArrayList<>();
collected.addAll( a1 );
collected.addAll( a2 );
return collected; }which can later be used as follows:List foos = collect( new ArrayList(), new ArrayList() );
or as follows:
List foos = collect( new ArrayList(), new ArrayList() );
note that none of the above would have worked if the collect method had been declared as follows:
List collect( List a1, List a2 )