javagenerics

What is a difference between <? super E> and <? extends E>?


What is the difference between <? super E> and <? extends E>?

For instance when you take a look at class java.util.concurrent.LinkedBlockingQueue there is the following signature for the constructor:

public LinkedBlockingQueue(Collection<? extends E> c)

and for one for the method:

public int drainTo(Collection<? super E> c)

Solution

  • The first (<? super E>) says that it's "some type which is an ancestor (superclass) of E"; the second (<? extends E>) says that it's "some type which is a subclass of E". (In both cases E itself is okay.)

    So the constructor uses the ? extends E form so it guarantees that when it fetches values from the collection, they will all be E or some subclass (i.e. it's compatible). The drainTo method is trying to put values into the collection, so the collection has to have an element type of E or a superclass.

    As an example, suppose you have a class hierarchy like this:

    Parent extends Object
    Child extends Parent
    

    and a LinkedBlockingQueue<Parent>. You can construct this passing in a List<Child> which will copy all the elements safely, because every Child is a parent. You couldn't pass in a List<Object> because some elements might not be compatible with Parent.

    Likewise you can drain that queue into a List<Object> because every Parent is an Object... but you couldn't drain it into a List<Child> because the List<Child> expects all its elements to be compatible with Child.