Essentially List<? extends String>
is a List of an unknown type, all that is known is that this type extends String. It does not matter that the variable contains an instance of List<String>
.
Now String is final, so there is no subclass... so let's consider:
List<? extends A> list = new ArrayList<A>();
where A
is some class with a subclass B
. When used, a variable of type List<? extends A>
might be an instance of List<B>
. We can not add A
to it because there is the possibility that an A
is not a B
.
But you know it will be right? Well, the compiler doesn't, nor does it anticipate the logical connections between the unknown type and what you've instantiated, because in general you may change that variable at runtime.
A similar example exist in the tutorial optimistically named More Fun with Wildcards, where a method accepts (Set<T>, T)
and an illegal call is preposed using (Set<?>, String)
though the Set<?>
variable contains an instance of Set<String>
. The issue is the same here, despite the addition of extends
.