Объяснение обобщенного <T extends Comparable <? супер T >> в коллекции .sort/сопоставимый код?

Я использую сопоставимый интерфейс все время, чтобы обеспечить естественный порядок для моего класса через collection.sort.

В принципе, если у меня есть класс person, я получу его для реализации интерфейса Comparable и предоставит реализацию compareTo. Однако в определении Collections.sort в javadocs я вижу эту подпись

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

Я вообще не понимаю это определение дженериков? Не стоит ли просто говорить

<T implements Comparable<T>>

Может кто-нибудь мне помочь?

Ответы

Ответ 1

Собственно, это означает, что T может реализовать Comparable<? super T>, а не только Comparable<T>.

Например, это означает, что класс Student может реализовать Comparable<Person>, где Student является подклассом Person:

public class Person {}

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

В этом случае список можно сортировать по Collections.sort(), но только на основе свойств Person, потому что вы передаете экземпляр Student в compareTo() как Person (если вы его не убьете, конечно).

Однако на практике вы никогда не увидите реализацию класса Student Comparable<Person>. Это потому, что Person, вероятно, реализовал Comparable<Person>, а Student наследует его реализацию. Конечный результат один и тот же: вы можете передать List<Student> в Collections.sort() и отсортировать его по свойствам Person.

Разница между Comparable<T> и Comparable<? super T> более очевидна в перегруженной версии Collections.sort(), которая принимает 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());

Ответ 2

Вы всегда используете расширения с подстановочными знаками generics, даже если параметр type реализует интерфейс.

Если вы посмотрите на класс, который реализует Comparable, вы увидите, что он фактически должен (должен) реализовать Comparable<T>, где T - сам класс.

Имеет смысл, если вы думаете о параметре типа, переданном в интерфейс Comparable и как он используется в compareTo().

Как красноречиво указывает PM 77-1, ключевое слово super позволяет либо классу, либо T, либо одному из его родителей реализовать Comparable.