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);
