1

This question may have been asked before in different formats but I just couldn't find an appropriate answer.

Whats the difference between these codes:

FIRST CODE

ArrayList<? super Number> list=new ArrayList<>(Arrays.asList(1));

SECOND CODE

ArrayList<? extends Number> list=new ArrayList<>(Arrays.asList(1));

Both statement compiles . Please justify why the former compiles . It shows Integer extends Number and Integer super Number too.

EDIT::

The answer I was looking forward to is: new ArrayList(Collection<? extends E>) hence both of them compile.

In that way this isn't a duplicate question as the referred answer doesn't describe that.

user2653926
  • 484
  • 4
  • 19

2 Answers2

0

They both execute the same way, but the compiler will prevent them from compiling in different ways.

public class NewClass {

    private List<? super Number> supers;

    private List<? extends Number> extenders;

    public NewClass() {
        supers = new ArrayList<>();
        extenders = new ArrayList<>();
    }

    public void addSupers() {
        supers.add(new Integer("5"));
    }

    public void addExtenders() {
        // This won't compile
        extenders.add(new Integer("5"));
    }

    public void getSupers() {
        // this won't compile
        Number number = supers.get(1);
    }

    public void getExtenders() {
        Number number = extenders.get(1);
    }

}

In the supers add case, you can safely add Integers as Integers have a super class Number. You can't do that in the extenders case because the extenders hold a particular subclass of Number, which in this case is determined by a wild card. In short, the extenders item is generally assumed to hold all the same sub-class of Number.

In the supers get case, you cannot safely pull out a Number because for some types, might not be Numbers but rather super-classes of Number, so the "down cast" is dangerous. However, in the extenders scenario, all the contents are assured to be sub-classes of Number so they all can safely be cast to Number.

Edwin Buck
  • 64,804
  • 7
  • 90
  • 127
0

<? super Number> means that the type is any superclass of Number.

<? extends Number> means that the type is any subclass of Number.

They'll compile to the same thing, but it depends what types you're actually going to do with your List.

If you have a List<? super Number>, you can put into it anything that is a Number, but the compiler can't guarantee that what you get out of it will be a Number. Whereas if you have a List<? extends Number>, then anything you get out will definitely inherit from Number.

The compiler will object if try and pass a List<? super Number> to a method expecting a List<? extends Number>, because the former might have stuff in that is not a Number.

The compiler will object if try and pass a List<? extends Number> to a method expecting a List<? super Number>, because the former can't necessarily receive elements that the latter can.

khelwood
  • 46,621
  • 12
  • 59
  • 83