Ради этого ответа возьмем Comparator
в качестве основного, руководящего примера.
Если вы внимательно об этом подумаете, вы увидите, что Comparator
на самом деле получает два аргумента типа T
и возвращает результат их сравнения (представленный int
).Другими словами, он потребляет два экземпляра типа T
, а создает и int
значение.Таким образом, согласно правилу PECS, это потребитель из T
, следовательно, использование ? super T
.
В более общем случае, вы должны рассмотреть производитель и потребитель с точки зрения основного типа в отношении типов каждого из его общих параметров.Если какой-то Comparator
тип потребляет объекты типа T
, правило PECS гласит, что пользователи такого Comparator<T>
могут использовать его для сравнения объектов, тип которых является подтипом T
.
В качестве конкретного примера, если у вас уже есть логика для сравнения двух общих Number
экземпляров (независимо от того, каков их конкретный тип на самом деле), вы можете использовать его, то есть для сравнения Double
экземпляров, потому что удваиваютсяв конце концов, числа.
Рассмотрим следующий компаратор:
Comparator<Number> c = Comparator.comparingInt(Number::intValue);
Здесь компаратор c
сравнивает Number
экземпляров ( любое число), принимая во вниманиеучитывайте только их неотъемлемую часть.
Если у вас есть следующий список Double
экземпляров:
List<Double> doubles = Arrays.asList(2.2, 2.1, 7.3, 0.2, 8.4, 9.5, 3.8);
и следующий sort
метод:
static <T> void sort(List<T> list, Comparator<T> c) {
list.sort(c);
}
(Обратите внимание на отсутствие подстановочного знака ? super T
в аргументе Comparator
).
Затем, если вы хотите отсортировать список List<Double> doubles
, подпись вышеуказанного метода sort
потребует от васпередать бетон Comparator<Double>
.Но что, если вы хотите использовать ранее определенный компаратор c
для сортировки List<Double> doubles
?
Поскольку тип этого компаратора равен Comparator<Number>
, а тип списка doubles
равен List<Double>
, следующий код вызовет ошибку компиляции:
sort(doubles, c);
К счастью, как Comparator
является потребителем типа элементов, которые он сравнивает, вы можете изменить сигнатуру метода sort
на:
static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
И теперь этот код будет компилироваться:
sort(doubles, c);