-5

This was closed as being a duplicate of the PECS question. PECS is just a mnemonic that does more harm than good because people just memorize it without really understanding the deeper issues. Please reopen.

Update:

What I understood from @rzswitzerloot's explanation below is: the wildcard just refers to the type of element in the Array. It does not mean one can add the wildcard type to the array - in fact, one can only add descendants of the type (including itself, in this case, 'B').


I am confused by whether wildcards <? super Number> refers to a superclass like Object or a subtype like Integer. In "Java OCP 17 Developer Complete Study Guide" by Jeanne Boyarsky and Scott Selikoff, (Chapter 9 Collections and Generics)

Generics allow you to specify wildcards. <?> is an unbounded wildcard that means any type. <? extends Object> is an upper bound that means any type that is Object or extends it. <? extends MyInterface> means any type that implements MyInterface. <? super Number> is a lower bound that means any type that is Number or a super class. A compiler error results from code that attempts to add an item in a list with an unbounded or upper-bounded wildcard

A super class as I understand, is a parent of Number. But then, why cannot one do this?

import java.util.ArrayList;
import java.util.List;

public class Bewildered {
    static class A {}
    static class B extends A {}
    static class C extends B {}

    public static void main(String[] args) {
        List<? super B> listBs = new ArrayList<>();
        listBs.add(new A());
    }
}

compile error:

java: incompatible types: Bewildered.A cannot be converted to capture#1 of ? super Bewildered.B
likejudo
  • 3,396
  • 6
  • 52
  • 107
  • The documentation you've included seems pretty clear on the subject. ` super Number>` would apply to `Object`, as its a superclass of `Number`. – CryptoFool Sep 29 '22 at 02:05
  • 2
    "` super Number>` is a lower bound that means any type ***that is Number*** or a super class" See that part? It doesn't necessarily have to be a superclass. `? super B` could be `B`, in which case adding an `A` is not allowed. – Sweeper Sep 29 '22 at 02:16
  • 1
    @CryptoFool but adding an Object will not compile – likejudo Sep 29 '22 at 03:00
  • @Sweeper I understand that it can take B. But why can't it take A? I tried and it gives a compile error. – likejudo Sep 29 '22 at 03:02
  • 4
    It does answer the question. I and others repeatedly explained to you in the comments why it answers the question. This is not a discussion forum; "I need the same material explained in a different way in order to understand it" is not a reason to have a separate question. – Karl Knechtel Sep 29 '22 at 03:09
  • 4
    "I understand that it can take B. But why can't it take A?" **For the reason carefully and repeatedly explained in the duplicate that was linked to you last time, and repeatedly re-stated in the comment discussion that ensued there**. – Karl Knechtel Sep 29 '22 at 03:10

1 Answers1

3

Because you're thinking about what generics means in the wrong way.

List<? super B> does not mean: "A list that contains Bs or anything that is a supertype of B".

Because that would be utterly useless. Object is a supertype of B. All things are objects. So it's a list of absolutely anything, there's absolutely nothing useful about this list.

No, what List<? super B> means: There is a type. A specific type. It's just.. this code doesn't know what it is. We do know that it is either B or some supertype of B. (So, it's B, or A, or Object, we don't know. The caller picked one of these 3 types). This list is constrained; it cannot contain anything that is not this unknown type.

The point is, you can do this:

List<B> bees = new ArrayList<B>();
List<? super B> list = bees; // legal!
list.add(new A()); // um...
B bee = bees.get(0); // oh no!

See how this goes wrong? There's only one list here - bees and list are both just variables that refer to the exacrt same list. So you if you call list.add, you're modifying the one list that both bees and list are pointing at, so you also add it to bees.

So what's the point of <? super B>?

You can call .add(new B()). Because that works for all legal choices. Whatever the caller picked - if they gave you a List<B>, it works. If it's a List<A>, works. List<Object>? Still acceptable.

No other types fit the bill for <? super B>, so we've exhausted the options: They all 'work out'.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72