Taken from https://stackoverflow.com/a/19231762/1498827
public class Test {
public class A {}
public class B extends A {}
public class C extends B {}
public void testContraVariance(List<? super B> myBlist) {
B b = new B();
C c = new C();
myBlist.add(b);
myBlist.add(c);
A a = myBlist.get(0); // does not compile
}
}
If myBlist accepts a super type of B ,which means B or up, then why can you also add a child to it as in myBlist.add(c)
?
CodePudding user response:
I think the question is specifically about the meaning of List<? super B>
. The OP wrote "myBlist
accepts ... B or up" and I think this is the root of the misunderstanding. List<? super B>
does not mean a list that can only contain elements of type B
or of a supertype of B
.
Instead, List<? super B>
is a list whose type parameter is B
or is a supertype of B
. Given the type hierarchy in the question, and this declaration:
public void testContraVariance(List<? super B> myBlist)
then myBlist
can be a List<B>
, a List<A>
, or a List<Object>
. Any of these types can contain a C
. That's why myBlist.add(c)
works.
CodePudding user response:
Every C
is-a B
. You should be comfortable with the notion of assigning an instance of C
to a variable of type B
:
B c = new C();
From there, it should not be surprising that this is valid:
List<? super B> myBlist = new ArrayList<Object>();
myBlist.add(c);