关于以下代码:
public class Test <T extends Comparable>{
public static void main(String[] args){
List<String> lst = Array.asList("abc","def");
System.out.println(func(lst));
}
public static boolean func(List<**here**> lst){
return lst.get(0).compareTo(lst.get(1)) == 0;
}
}
为什么要编写“?扩展了Comparable”?在此会编译,为什么不编写“ Comparable”?
提前谢谢。
答案 0 :(得分:8)
之所以会这样,是因为泛型是不变。即使String
是一个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) {
.....
}
答案 1 :(得分:1)
这是因为无法将List<SubClass>
强制转换为List<BaseClass>
。让我们假设它可以
List<String> sList = new ArrayList<>();
List<Comparable> cList = (List<Comparable>) sList;
cList.add(5);
这将是一个问题,因为整数5不是String
,并且不应放在List<String>
中。
通过使用? extends Comparable
,您是说该函数可以获取具有Comparable作为基类的所有内容的列表(例如List<Comparable>
,List<String>
,List<Integer>
等)
要更正确地定义函数,您应该执行以下操作:
public static <T extends Comparable<T>> boolean func(List<T> lst) {}
这将强制类型与其自身具有可比性。您的函数会比较列表中的第一个元素和第二个元素,因此最好确保列表中的每个元素实际上都与其他元素具有可比性。
答案 2 :(得分:0)
因为
List<String> lst = Array.asList("abc","def");
lst
列表具有通用类型String
,而不是Comparable
。
String
类,更完善,实现了Comparable<String>
接口,因此它适合于? extends Comparable
泛型类型。