Thursday, October 31, 2013

I'm having trouble understanding the following syntax:
public class SortedList< T extends Comparable< ? super T> > extends LinkedList< T >
I see that class SortedList extends LinkedList. I just don't know what
T extends Comparable< ? super T>
means.
My understanding of it so far is that type T must be a type that implements Comparable...but what is < ? super T >?
share|improve this question

5 Answers

up vote18down voteaccepted
super in Generics is the opposite of extends. Instead of saying the comparable's generic type has to be a subclass of T, it is saying it has to be a superclass of T. The distinction is important because extends tells you what you can get out of a class (you get at least this, perhaps a subclass). super tells you what you can put into the class (at most this, perhaps a superclass).
In this specific case, what it is saying is that the type has to implement comparable of itself or its superclass. So consider java.util.Date. It implements Comparable. But what about java.sql.Date? It implements Comparable as well.
Without the super signature, SortedList would not be able accept the type of java.sql.Date, because it doesn't implement a Comparable of itself, but rather of a super class of itself.
share|improve this answer
 
I see. So then given that class, would Collection< Object > list = new SortedList< Object>(); be a valid statement? –  ShrimpCrackers May 13 '10 at 14:36 
 
@aloh, no it would not because Object does not implement Comparable. –  Yishai May 13 '10 at 14:37 
 
Whoops. Oh, yeah. Thanks Yishai. –  ShrimpCrackers May 13 '10 at 14:40
It's a lower-bounded wildcard.

JLS 4.5.1 Type Arguments and Wildcards

Wildcards are useful in situations where only partial knowledge about the type parameter is required. [...] An upper bound is signified by the syntax:
? extends B
where B is the upper bound. [...] it is permissible to declare lower bounds on a wildcard, using the syntax:
? super B
where B is a lower bound.
List, for example, includes ListList, andList.
Wildcards are used to make generics more powerful and flexible; bounds are used to maintain type safety.

See also


As to how this is useful in >, it's when you have something likeCat extends Animal implements Comparable.
Look at the signature of Collections.sort
public static <T extends Comparable super T>> void sort(List<T> list)
Therefore, with a List listOfCat, you can now Collections.sort(listOfCat).
Had it been declared as follows:
public static <T extends Comparable<T>> void sort(List<T> list)
then you'd have to have Cat implements Comparable to use sort. By using the ? super T bounded wildcard, Collections.sort becomes more flexible.

See also

  • Effective Java 2nd Edition, Item 28: Use bounded wildcards to increase API flexibility
    • Also, PECS principle: "producer extends consumer super"
share|improve this answer
 
It's a bit more complicated than that though - the question isn't about ? super T, it is about T extends Comparable –  oxbow_lakes May 13 '10 at 14:31
 
Ah, I see. Those all implement Comparable. What about the super keyword? –  ShrimpCrackers May 13 '10 at 14:33
 
Not really! If you look at docs, you'll realize it's not simply a bounded wildcard. –  Epitaph May 13 '10 at 14:34
 
Just for clarification, my previous comment was aimed at your initial response which was just 3-4 lines. – Epitaph May 13 '10 at 16:35
It means that T must implement Comparable The sense is that because SortedList is sorted, it must know how to compare two classes of its genericsT parameter. That's why T must implement Comparable
share|improve this answer
It means that the type T must implement Comparable of T or one of its super classes.
For example, if A extends B, if you want to use SortedListA must implementComparable or Comparable, or in fact just Comparable.
This allows the list of As to be constructed with any valid comparator.
share|improve this answer
Consider the following example:
  1. Using a type parameter defined in the class declaration
    public class ArrayList extends AbstractList ... {
    public boolean add(E o) // You can use the "E" here ONLY because it's already been defined as part of the class
  2. Using a type parameter that was NOT defined in the class declaration
    public <T extends Animal> void takeThing(ArrayList<T> list)
                                                // Here we can use  because we declared "T" earlier in the method declaration                  
    If the class itself doesn't use a type parameter, you can still specify one for a method, by declaring it in a really unusual (but available) space - before the return type. This method says that T can be "any type of Animal".
NOTE:
public <T extends Animal> void takeThing(ArrayList<T> list)             

is NOT same as              

public void takeThing(ArrayList<Animal> list)
Both are legal, but they are different. The first one indicates that you can pass in a ArrayList object instantiated as Animal or any Animal subtype like ArrayList, ArrayList or ArrayList. But, you can only pass ArrayList in the second, and NOT any of the subtypes.
share|improve this answer