How are the Java generic extends - Foo> and different?

362    Asked by AnilJha in Java , Asked on Oct 12, 2022

 I seem to have a misunderstanding about the difference between and <? extends Foo>. From my understanding, if we had


ArrayList 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 foos = new 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 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?

Answered by Anisha Dalal

As you have discovered by yourself, an ArrayList declared as ArrayList subFoos = new ArrayList<>(); would not be very useful.


In order to see the usefulness of 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 )


Your Answer

Interviews

Parent Categories