Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collections.sort() declaration: why <? super T> rather than <T>

Tags:

Why does Collections.sort(List<T>) have the signature :

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

and not :

public static <T extends Comparable<T>> void sort(List<? extends T> list) 
  • I understand that they both would serve the same purpose; so why did the framework developers use the first option?
  • Or are these declarations really different?
like image 561
prvn Avatar asked Mar 01 '16 05:03

prvn


People also ask

What does <? Super t mean in Java?

super T denotes an unknown type that is a supertype of T (or T itself; remember that the supertype relation is reflexive). It is the dual of the bounded wildcards we've been using, where we use ? extends T to denote an unknown type that is a subtype of T .

What does collection sort () do?

By default, Collection. sort performs the sorting in ascending order. If we want to sort the elements in reverse order we could use following methods: reverseOrder() : Returns a Comparator that imposes the reverse of natural ordering of elements of the collection.

Does collections sort use compareTo?

Collections class has a second sort() method and it takes Comparator. The sort() method invokes the compare() to sort objects.

How does collections sort work in Java?

Collections sort is a method of Java Collections class used to sort a list, which implements the List interface. All the elements in the list must be mutually comparable. If a list consists of string elements, then it will be sorted in alphabetical order.


1 Answers

Your proposed signature would probably work in Java-8. However in previous Java versions type inference was not so smart. Consider that you have List<java.sql.Date>. Note that java.sql.Date extends java.util.Date which implements Comparable<java.util.Date>. When you compile

List<java.sql.Date> list = new ArrayList<>(); Collections.sort(list); 

It perfectly works in Java-7. Here T is inferred to be java.sql.Date which is actually Comparable<java.util.Date> which is Comparable<? super java.sql.Date>. However let's try your signature:

public static <T extends Comparable<T>> void sort(List<? extends T> list) {}  List<java.sql.Date> list = new ArrayList<>(); sort(list); 

Here T should be inferred as java.util.Date. However Java 7 specification does not allow such inference. Hence this code can be compiled with Java-8, but fails when compiled under Java-7:

Main.java:14: error: method sort in class Main cannot be applied to given types;         sort(list);         ^   required: List<? extends T>   found: List<Date>   reason: inferred type does not conform to declared bound(s)     inferred: Date     bound(s): Comparable<Date>   where T is a type-variable:     T extends Comparable<T> declared in method <T>sort(List<? extends T>) 1 error 

Type inference was greatly improved in Java-8. Separate JLS chapter 18 is dedicated to it now, while in Java-7 the rules were much simpler.

like image 138
Tagir Valeev Avatar answered Sep 22 '22 08:09

Tagir Valeev