Differences between extend and super in Generics


For example, the following code:

public void add(List<? super Number> list) {
    list.add(1D); // можно
    list.add(new Object()); // нельзя
}

Why is that? After all, here - <? super Number> - it says: "any type that is a super-class for Number". And it works the other way around: "any type is the heir of Number". What's wrong? Why does it work the other way around?

Author: Regent, 2017-01-11

2 answers

Yes, <? super Number> does imply "any type that is a superclass for Number". Plus himself Number.

For this reason, you can pass to the method, for example, List<Object>.

Since the type of elements in this list is "something that is a superclass for Number", you can add elements to the list whose type is a child of Number. For example, Integer:

public void add(List<? super Number> list)
{
    list.add(1);
}

This is allowed, since you can add elements to the list whose type is a child of the type list items. As in the case of the usual List<Number>:

List<Number> list = new ArrayList<>();
list.add(1);

However, you can't add new Object() to the list, because there are no guarantees that the list can store elements of the type Object: under ? can "hide" not only Object, but also, for example, the Number itself. In the case of other classes (? super X) that have intermediate classes between Object and X itself, there is also any intermediate class.

Since the true type of the list items is unknown (?), but any class has in as a superclass of Object, then you can only work with the element obtained from the list as Object. Even with the unit that you just put there yourself.


In the case of <? extends Number>, it means " any type that is a child class of Number". Plus himself Number.

In this case, you can pass to the method, for example, List<integer>.

Since the element type is "something that is a child class for Number", then you will not be able to add anything to the list (except, perhaps what, null), for it is not known what exactly can be stored there.

But you can work with the element obtained from the list as with Number:

public static void add2(List<? extends Number> list)
{
    int value = list.get(0).intValue();
}

Because whatever the elements in the list are, they are definitely from the child classes of Number, which means they can work as Number.

 10
Author: Regent, 2017-01-11 08:19:44

It's very simple.

The definition of List'a with wildcard of the form <? super Number> indicates that the list contains elements of some type from which Number is inherited. There doesn't have to be a Object here, there can also be some intermediate class in the inheritance hierarchy.

For example.
There are classes A,B,C. A inherited from B, B in turn, it is inherited from C.
If we write List<? super A>, it means that the list can be like List<A>,List<B> or List<C>. Accordingly, if List<B> comes, then putting elements of the C type there will be an error. The compiler warns you against this error.

 3
Author: Artem Konovalov, 2017-01-11 07:47:08