List<? extends B1>
means: a list of an unknow type, which is or extends B1. So it could be a List<B1>
, a List<C1>
, or a List<Foo>
if Foo
also extends B1
or C1
. So you can't add anything to such a list:
list.add(new A1); // incorrect, since A1 doesn't even extend B1
list.add(new B1()); // incorrect, since the list could be a List<C1>
list.add(new C1()); // incorrect, since the list could be a List<Foo>
The only thing you can add to such a list is null.
List<? super B1>
means: a list of an unknow type, which is B1 or a superclass or superinterface of B1
. So it could be a List<B1>
, a List<A1>
, or a List<Object>
(and nothing else). So
list.add(new A1()); // incorrect, since the list could be a List<B1>, and A1 is not a B1
list.add(new B1()); // valid, since whatever the type of the list (B1, A1 or Object), B1 is of this type
list.add(new C1()); // valid, since whatever the type of the list (B1, A1 or Object), B1 is of this type
If you try to get an element from such a list, though, you can't have any guarantee about its type. The only sure thing is that it's an Object.
The general principle is PECS: Producer Extends, Consumer Super. This means that when a list is a producer (which means you want to get elements from it), then extends
should be used. When the list is a consumer (which means you want to add elements to it), then super
should be used.