(I assume here that Bar
and Baz
are both subtypes of Foo
.)
List<? extends Foo>
means a list of elements of some type, which is a subtype of Foo, but we don’t know which type. Examples of such lists would be a ArrayList<Foo>
, a LinkedList<Bar>
and a ArrayList<Baz>
.
As we don’t know which subtype is the type parameter, we can’t put Foo
objects into it, neither Bar
or Baz
objects. But we still know that the type parameter is a subtype of Foo
, so every element already in the list (and which we can get from the list) must be a Foo
object, so we can use Foo f = list.get(0);
and similar things.
Such a list can only be used for taking elements out of the list, not to adding elements at all (apart from null
, but I don’t know if the compiler actually allows this).
A List<Foo>
on the other hand allows adding any object which is a Foo
object – and as Bar
and Baz
are subtypes of Foo
, all Bar
and Baz
objects are Foo
objects, so they can be added, too.