Расслабление общей сигнатуры может повысить гибкость кода, особенно когда мы говорим о типах параметров.Общее руководство - это правило PECS , но для Comparable
практические примеры необходимости такой гибкости редки, поскольку они подразумевают наличие базового типа, определяющего естественный порядок среди всех его подтипов.
Например, если у вас есть метод, подобный
public static <T extends Comparable<T>> void sort(Collection<T> c) {
}
, вы не можете выполнить следующее
List<LocalDate> list = new ArrayList<>();
sort(list); // does not compile
Причина в том, что LocalDate
реализует ChronoLocalDate
, и вы можете сравнить всереализации ChronoLocalDate
друг с другом, другими словами, все они реализуют Comparable<ChronoLocalDate>
.
Таким образом, сигнатура метода должна быть
public static <T extends Comparable<? super T>> void sort(Collection<T> c) {
}
, чтобы позволить фактическим типам реализовать Comparable
параметризован с типом super, точно так же, как было объявлено Collections.sort
.
Для конкретного случая siftUpComparable
, т. Е. Внутренний метод Collection, у которого нет шансовдля определения фактической общей сигнатуры действительно не имеет значения, использует ли он Comparable<T>
или Comparable<? super T>
, поскольку все, что ему нужно, - это возможность передать экземпляр T
методу compare
, в то время как даже обеспечиваетфактический аргументв любом случае выполняется другим неконтролируемым приведением.
Фактически, поскольку приведение типа не проверено , оно могло бы быть также приведено к Comparable<Object>
, что исключило бы необходимость выполнения(T)
приведение при вызове compare
.
Но, очевидно, автор не намеревался слишком далеко уходить от того, что будет делать настоящий универсальный код, и использовал тот же шаблон, даже если он не имееточевидная выгода здесь.