tags:

views:

637

answers:

5

I wonder if you could explain to me what is a difference between: <? super E> and <?extends E>.

For instance when you take a look at class java.util.concurrent.LinkedBlockingQueue there is a following signature for constructor: public LinkedBlockingQueue(Collection<? extends E> c) and for one for the method: public int drainTo(Collection<? super E> c).

+10  A: 

The first says that it's "some type which is an ancestor of E"; the second 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.

Jon Skeet
+1. That is really the practical difference. extends to fetch, super to insert.
Yishai
Many thanks. Great explanation!
pregzt
+2  A: 

You might want to google for the terms contravariance (<? super E>) and covariance (<? extends E>). I found that the most useful thing when comprehending generics was for me to understand the method signature of Collection.addAll:

public interface Collection<T> {
    public boolean addAll(Collection<? extends T> c);
}

Just as you'd want to be able to add a String to a List<Object>:

List<Object> lo = ...
lo.add("Hello")

You should also be able to add a List<String> (or any collection of Strings) via the addAll method:

List<String> ls = ...
lo.addAll(ls)

However you should realize that a List<Object> and a List<String> are not equivalent and nor is the latter a subclass of the former. What is needed is the concept of a covariant type parameter - i.e. the <? extends T> bit.

Once you have this, it's simple to think of scenarios where you want contravariance also (check the Comparable interface).

oxbow_lakes
+1  A: 

A wildcard with an upper bound looks like " ? extends Type " and stands for the family of all types that are subtypes of Type , type Type being included. Type is called the upper bound .

A wildcard with a lower bound looks like " ? super Type " and stands for the family of all types that are supertypes of Type , type Type being included. Type is called the lower bound .

vinaynag
+1  A: 

<? extends E> defines E as the upper bound: "Something that can be cast to E".

<? super E> defines E as the lower bound: "Something that E can be cast to."

David Moles
+2  A: 

I'm going to try and answer this. But to get a really good answer you should check Joshua Bloch's book Effective Java (2nd Edition). He describes the mnemonic PECS, which stands for "Producer Extends, Consumer Super".

The idea is that if you code is consuming the generic values from the object then you should use extends. but if you are producing new values for the generic type you should use super.

So for example:

public void pushAll(Iterable<? extends E> src) {
  for (E e: src) 
    push(e);
}

And

public void popAll(Collection<? super E> dst) {
  while (!isEmpty())
    dst.add(pop())
}

But really you should check out this book: http://java.sun.com/docs/books/effective/

joekutner