38

I use comparable interface all the time to provided natural ordering for my class through collection.sort.

Basically if I have a person class, I will get it to implement Comparable interface and will provide the implementation of compareTo. However in the definition of Collections.sort in javadocs, I see this signature

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

I don't understand this generics definition at all? Shouldn't it just say

<T implements Comparable<T>>

Can someone help me with this?

skiwi
  • 66,971
  • 31
  • 131
  • 216
Max
  • 9,100
  • 25
  • 72
  • 109
  • 17
    It means that either the class `T` itself or one of its super classes implements `Comparable`. – PM 77-1 Sep 11 '14 at 04:45
  • @PM77-1 Thank you for this simplistic explanation and it appears that `>` is the most correct – Mushy Sep 14 '17 at 19:28

2 Answers2

56

Actually, it means that T can implement Comparable<? super T>, not just Comparable<T>.

For example, it means that a Student class can implement Comparable<Person>, where Student is a subclass of Person:

public class Person {}

public class Student extends Person implements Comparable<Person> {
    @Override public int compareTo(Person that) {
        // ...
    }
}

In this case, a List can be sorted by Collections.sort() but only based on Person's properties, because you pass the Student instance into compareTo() as a Person (unless you downcast it, of course).

In practice however, you'll never see a Student class implement Comparable<Person>. That's because Person will probably have implemented Comparable<Person>, and Student inherits it implementation. The end result is the same however: you can pass a List<Student> to Collections.sort() and have it sorted on Person's properties.

The difference between Comparable<T> and Comparable<? super T> is more obvious in the overloaded version of Collections.sort() that takes a Comparator<? super T>:

class ByAgeAscending implements Comparator<Person> {
    @Override public int compare(Person a, Person b) {
        return a.getAge() < b.getAge();
    }
}

List<Student> students = getSomeStudents();
Collections.sort(students, new ByAgeAscending());
Jan Van den bosch
  • 3,542
  • 3
  • 26
  • 38
6

You always use extends with generics wildcards, even if the type parameter implements an interface.

If you look at a class that implements Comparable, you'll see that it actually (should) implement Comparable<T>, where T is the class itself.

It makes sense if you think about the type paramter passed to the Comparable interface and how it's used in the compareTo() method.

As PM 77-1 has eloquently pointed out, the super keyword allows for either the class, T, or one of its parents to implement Comparable.

jahroy
  • 22,322
  • 9
  • 59
  • 108