Это происходит потому, что дженерики инвариантны . Даже если String
равно a Comparable
, что означает:
String s = "";
Comparable c = s; // would work
Общие из них не будут работать:
List<Comparable> listC = List.of();
List<String> listS = List.of();
listC = listS; // will fail
И это не сработает, независимо от того, каковы отношения между Comparable
и String
.
Когда вы меняете определение этого метода на:
public static boolean func(List<? extends Comparable> lst) {
...
}
Говорят, что: Подстановочный знак с расширением-границей делает тип ковариантным.
Это означает, что:
List<? extends Comparable> listC = List.of();
List<String> listS = List.of();
listC = listS; // would work here
Или, проще говоря, это означает, что List<String>
является подтипом из List<? extends Comparable>
.
Сейчас нужно заплатить небольшую цену, потому что listC
теперь является производителем элементов, что означает, что вы можете извлекать из него элементы, но не можете ничего в него вкладывать.
И вскоре после того, как вы это поймете, вы еще не закончили, потому что определение этого метода было бы совершенно правильным, если было бы написано так:
public static <T extends Comparable<? super T>> boolean func(List<T> lst) {
.....
}