107

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 >?

vidit
  • 6,007
  • 3
  • 28
  • 46
ShrimpCrackers
  • 4,040
  • 14
  • 47
  • 69

5 Answers5

108

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<Date>. But what about java.sql.Date? It implements Comparable<java.util.Date> 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.

Yishai
  • 84,976
  • 26
  • 176
  • 250
  • 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
  • 1
    @aloh, no it would not because Object does not implement Comparable. – Yishai May 13 '10 at 14:37
  • I am sorry, I know the question is a bit old, but what can we say if we instead write `Comparable extends T>`. What would it mean and why the code does not compile? – tonix Dec 03 '17 at 00:17
  • @tonix in that case we are saying that type ? must be a subclass of this generic type T, e.g. if we say T is Number, the ? must be Integer,Double, Short etc – jbailie1991 Feb 27 '18 at 14:27
95

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.

A List<? super Integer>, for example, includes List<Integer>, List<Number>, and List<Object>.

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 <T extends Comparable<? super T>>, it's when you have something like Cat extends Animal implements Comparable<Animal>.

Look at the signature of Collections.sort

public static <T extends Comparable<? super T>> void sort(List<T> list)

Therefore, with a List<Cat> 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<Cat> 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"
Community
  • 1
  • 1
polygenelubricants
  • 348,637
  • 121
  • 546
  • 611
15

It means that T must implement Comparable<T itself or one of T's superclasses> The sense is that because SortedList is sorted, it must know how to compare two classes of its generics T parameter. That's why T must implement Comparable<T itself or one of T's superclasses>

Petar Minchev
  • 44,805
  • 11
  • 98
  • 117
5

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 SortedList<A>, A must implement Comparable<A> or Comparable<B>, or in fact just Comparable.

This allows the list of As to be constructed with any valid comparator.

John Smith
  • 321
  • 1
  • 5
4

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 <T> 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.

Epitaph
  • 2,902
  • 10
  • 32
  • 42