1

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

Thomas
  • 174,939
  • 50
  • 355
  • 478
microwth
  • 1,016
  • 1
  • 14
  • 27
  • 7
    Because `C` is implicitly convertible to `B`. It would be odd to prevent `myBlist.add(c);` but to allow `B tmp = c; myBlist.add(tmp);`. They do the same thing, so why would you want to force users to write unwieldy code? (Or `myBlist.add((B) c);` where the cast is guaranteed to succeed...) – Jon Skeet Sep 27 '22 at 09:36
  • 1
    This question was just closed as a duplicate of a question whose answer was cited in this question. Presumably the OP has read that question and other answers and is seeking clarification about this particular answer. OP can you clarify your question? (Reopened.) – Stuart Marks Sep 27 '22 at 21:12

2 Answers2

7

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.

Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
1

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);
erickson
  • 265,237
  • 58
  • 395
  • 493
  • See also [this answer,](https://stackoverflow.com/a/73142781/3474) where I struggled mightily to convey this understanding. – erickson Sep 27 '22 at 21:27