Объяснение универсального <T расширяет Comparable <? супер T >> в collection.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>>
Может кто-то помочь мне с этим?
2 ответа
На самом деле, это означает, что 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());
Вы всегда используете подстановочные знаки с универсальными подстановочными знаками, даже если параметр типа реализует интерфейс.
Если вы посмотрите на класс, который реализует Comparable, вы увидите, что он на самом деле (должен) реализовать Comparable<T>
где T сам класс.
Это имеет смысл, если вы подумаете о параметре типа, передаваемом в интерфейс Comparable, и о том, как он используется в методе compareTo().
Как красноречиво указывает PM 77-1, ключевое слово super позволяет классу T или одному из его родителей реализовать Comparable.