tags:

views:

81

answers:

4

The title says it all really. What's the difference between:

SomeClass<T extends OtherClass>

and

SomeClass<T super OtherClass>

Thanks

A: 
  • In the first case, OtherClass and any subclass is applicable as type parameter. This is useful for collections, where you want to restrict elements to Figure (including Rectangle and Circle) but not any other objects that are not figures. Thus we limit the collection to Group<? extends Figure>.

  • In the latter case, OtherClass and any superclass is applicable as type parameter. This is useful if you need to pass a Comparator to a collection of figures: this comparator should only assume that the elements are figures or more general. A comparators that expected every object to be Object or Figure will work, but a comparator that assumes that all elements are Rectangle will fail if it encounters for example a Circle. Thus we limit the comparator to Comparator<? super Figure>.

Adrian
+3  A: 

Sun says (from Using and Programming Generics in J2SE 5.0)

There are three types of wildcards:

  1. "? extends Type": Denotes a family of subtypes of type Type. This is the most useful wildcard
  2. "? super Type": Denotes a family of supertypes of type Type
  3. "?": Denotes the set of all types or any

More Fun with Wildcards gives some good examples to all three types.


Another good example (taken from the video recommended by @Adrian) is:

class Stack<E> {
    void pushAll( Collection<? extends E> src );
    void popAll( Collection<? super E> dest );
}

Here you can see the difference between super and extends:

For the method pushAll imagine you have a Stack<Number>. You want to push all elements of src to the Stack. But src should be able to be a Collection<Integer>. This is why you choose ? extends E here.

For the method popAll imagine you have a Stack<Integer>. You want to pop all elements of the Stack to dest. But dest should be able to be a Collection<Number>. This is why you choose ? super E here.

tangens
+1 for the Stack example.
Grundlefleck
+1  A: 

The difference is in the answer to the question "Which types are subtypes of SomeClass?". This is obviously an interesting question in Java since much of the power of the language comes from the ability to substitute sub types. Now, with

SomeClass<T extends OtherClass>

the subtypes are all those SomeClass<S> where S is a subtype of T. For example, the subtypes of

SomeClass<T extends List>

include SomeClass<LinkedList> and SomeClass<ArrayList>. But with

SomeClass<T super OtherClass>

the subtypes are all those SomeClass<S> where S is a supertype of T. For example, the subtypes of

SomeClass<T super LinkedList>

include SomeClass<List> and SomeClass<Collection>.

jjerms
+1  A: 

tangens' answer is correct, this is just (perhaps) useful information to accompany that answer.

There is a good explanation of how to use the two different wildcards in Josh Bloch's Effective Java 2nd Edition. It is also described in this video.

A mnemonic he uses is PECS - Producer Extends, Consumer Super. This is explained in the video and the book. This is a paraphrasing of one of the slides used in the talk:


PECS - Producer extends Consumer super

  • For a T producer use Foo<? extends T>
  • For a T consumer use Foo<? super T>

This only applies to input parameters, don't use wildcard types as return types.


Grundlefleck