我正在尝试为实现MyInterface的任何类的对象List实现通用排序实用程序方法。根据Java API(http://java.sun.com/javase/6/docs/api/java/util/Collections.html),Collections.sort()方法签名为:
public static <T> void sort(List<T> list, Comparator<? super T> c)
我不确定带有通配符参数的List是否可以替换“普通”参数化列表,但我尝试过:
static void mySort(List<? extends MyInterface> myList, SortCriteria mySortCriteria) {
Collections.sort(myList, new Comparator<? super MyInterface>() {
...
});
}
并且出现编译时错误,
The type new Comparator(){} cannot extend or implement Comparator<? super MyInterface>
A supertype may not specify any wildcard.
所以,我把它改为:
static void mySort(List<? extends MyInterface> myList, SortCriteria mySortCriteria) {
Collections.sort(myList, new Comparator<MyInterface>() {
...
});
}
它编译并运作。有什么好的解释吗?
答案 0 :(得分:2)
你在这里使用 contravariance 。
基本上,你需要一个可以比较列表中任何两个项目的比较器。如果列表是T
类型,这意味着它必须能够比较任何两个类型为T的项 - 但是如果它可以比较某些类型X的任何两个项,其中T是X的子类,那么那也没关系。
举一个我最喜欢的例子,如果你有一个比较器可以按区域比较任何两个形状,那么你可以清楚地用它来比较任何两个三角形 - 所以可以使用{{List<Triangle>
进行排序1}}。
我不确定你在最后一段中的“当我尝试它时”是什么意思...如果你能给出一个不起作用的简短而完整的例子,我们可以尝试解释原因。
编辑:好的,您无法在AreaShapeComparator
表达式中使用? extends X
或? extends Y
- 您只能将它们用作声明的一部分,无论是方法还是类型或变量。构造 new 对象时,需要指定确切的类型。
答案 1 :(得分:1)
我不明白这种约束对比较器的影响
约束说比较器必须能够至少比较它的List
,或超类型的泛型类型。例如,使用Comaparator<Number>
对List<Integer>
进行排序是有效的。如果Comparator
能够比较Number
s,那么它当然能够比较Integer
s。