1

This code

static void writeTo(List<? super Apple> apples) {
        apples.add(new Apple());
        apples.add(new Jonathan());
    }

The author of this code stated that

The argument apples is a List of some type that is the base type of Apple; thus you know that it is safe to add an Apple or a subtype of Apple. Since the lower bound is Apple,

Jonathan is a subclass of Apple.

But when I tried this

    List<Jonathan> loj = new ArrayList<Jonathan>();
    listSuper(loj);

It gave me this error

The method listSuper(List<? super Apple>) in the type Basket<T> is not applicable for the arguments (List<Jonathan>)

Where listSuper looks like this

static void listSuper (List<? super Apple> cont) {}

How does the two differ?

Also what confuses me on the first code that I posted is that I thought ? super T means that any base type of T. but from the looks of it he added a subtype of T. I am confused.

KyelJmD
  • 4,682
  • 9
  • 54
  • 77

5 Answers5

6

List<? super Apple> means a List you can add an Apple to (and since Jonathan is an Apple, you can put Jonathans into a List of that type as well).

It can be List<Apple>, List<Fruit> or List<Object>, but not List<Jonathan>, since you cannot put arbitrary Apples into List<Jonathan>. As you can see, in this case ? can be an Apple or any of its superclasses.

List<? extends Apple> means a List you can get an Apple from. It can be List<Apple> or List<Jonathan>, but not List<Fruit>, since List<Fruit> is not guaranteed to contain only Apples.

This explanation is known as "producer - extends, consumer - super" rule: if parameter acts as a consumer of elements, it should be declared with super, and vice versa.

axtavt
  • 239,438
  • 41
  • 511
  • 482
4

Jonathan is a subtype of Apple, not a supertype. It would match <? extends Apple> but does not match <? super Apple>

verdesmarald
  • 11,646
  • 2
  • 44
  • 60
  • But how come he added a Jonathan inside the a list of apples? in the writeTo method? – KyelJmD Sep 06 '12 at 14:08
  • There is no problem adding an instance of `Jonathan` to a `List`, why would there be? That is totally different to what you are trying to do... – verdesmarald Sep 06 '12 at 14:13
0

The author of the code was wrong. You can't pass a subclass of Apple to a method that takes ? super Apple, only Apple itself and superclasses of Apple. If you want to be able to add subclasses of Apple, you need to use ? extends Apple.

Tobb
  • 11,850
  • 6
  • 52
  • 77
  • You are wrong, read the top answers. A list of type ? super Apple can take Apple and all its subtypes. A list of type ? extends Apple cannot have anything added to it at all, but you are always getting apples from it. – Stefan Sep 06 '12 at 15:30
0

The type parameter must be a supertype of Apple, not a subclass, which is what Jonathan is. So, for instance, this would be valid:

List<Fruit> loj = new ArrayList<Fruit>();     
listSuper(loj); 
GriffeyDog
  • 8,186
  • 3
  • 22
  • 34
0

How does the two differ?

Also what confuses me on the first code that I posted is that I thought ? super T means that any base type of T. but from the looks of it he added a subtype of T. I am confused.

You must distinguish between (1) what you can insert into a generic list and (2) what can be sent as an argument to method with a generic list parameter.

  1. You can insert subtypes of Apple into apples because the bound type parameter is a base class which has the ability to reference all its subtypes.

  2. If Jonathan isn't a super type of Apple, then it's generically incorrect to try and send a list of Jonathan to that method, since I'd be allowed to insert Apples into a list of Jonathans. Then you'd have references of type Jonathan accessing the properties and methods of objects it knows nothing about, which isn't type-safe.

blackcompe
  • 3,180
  • 16
  • 27