所以我正在阅读泛型方法,我感到困惑。我先说一下这个问题:
在这个例子中:假设我需要一个适用于任何类型T的selectionSort版本,方法是使用调用者提供的外部可比较。
首次尝试:
public static <T> void selectionSort(T[] arr, Comparator<T> myComparator){....}
假设我有:
现在,我这样做:
selectionSort(arr, myComparator);
并且它不起作用,因为myComparator不适用于Vehicle的任何子类。
然后,我这样做:
public static <T> void selectionSort(T[] arr, Comparator<? super T> myComparator){....}
这个宣言可行,但我不完全确定我一直在做什么......我知道使用是要走的路。如果“?super T”的意思是“一个未知的超类型T”,那么我是强加上限还是上限?为什么超级?我的目的是让T的任何子类使用myComparator,为什么“?super T”。如此困惑......如果您对此有任何见解,我将不胜感激。
提前致谢!
答案 0 :(得分:5)
首先,您可以通过Vehicle[]
将Truck
添加到其中来解决问题。
您需要<? super T>
的原因可以追溯到Comparator<Truck>
不是Comparator<Vehicle>
的子类型的泛型规则;无界类型T
必须完全匹配,而不是。
为了传入合适的Comparator
,它必须是被比较的类的Comparator
或它的任何超类,因为在OO语言中,任何类都可以被视为超类的实例。因此,Comparator
的泛型类型无关紧要,只要它是数组组件类型的超类型。
答案 1 :(得分:3)
古怪的短语? super T
表示目的地列表可能包含任何类型的元素
这是T
的超类型,就像源列表可能包含任何类型的元素一样
T
的子类型。
我们可以从copy
看到非常简单的示例Collections
:
public static <T> void copy(List<? super T> dst, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dst.set(i, src.get(i));
}
}
并致电:
List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);
Collections.copy(objs, ints);
assert objs.toString().equals("[5, 6, four]");
与任何通用方法一样,可以推断出类型参数,也可以明确给出。在这种情况下,有四种可能的选择,所有选择都是类型检查,所有选择都具有相同的效果:
Collections.copy(objs, ints);
Collections.<Object>copy(objs, ints);
Collections.<Number>copy(objs, ints);
Collections.<Integer>copy(objs, ints);
答案 2 :(得分:2)
您的选择排序方法
public static <T> void selectionSort(T[] arr, Comparator<? super T> myComparator)
表示如果使用类型为T
的数组调用它,则必须提供类型为T的Comparator
或T
的超类型。
例如,如果您有以下类
class Vehicle {}
class Truck extends Vehicle {}
class BigTruck extends Truck {}
class VehicleComparator implements Comparator<Vehicle> {
public int compare(Vehicle o1, Vehicle o2) {
return 0;
}
}
class BigTruckComparator implements Comparator<BigTruck> {
public int compare(BigTruck o1, BigTruck o2) {
return 0;
}
}
class TruckComparator implements Comparator<Truck> {
public int compare(Truck o1, Truck o2) {
return 0;
}
}
比这更有用
Truck[] trucks = ...;
selectionSort(trucks, new TruckComparator());
selectionSort(trucks, new VehicleComparator());
因为
TruckComparator
实现Comparator<Truck>
,Truck
等于数组的类型Truck
VehicleComparator
实现Comparator<Vehicle>
,Vehicle
是数组类型的超级类型Truck
这将不工作
selectionSort(trucks, new BigTruckComparator());
你现在应该猜到为什么。
因为BigTruckComparator
是Comparator<BigTruck>
而BigTruck
不是数组类型Truck
的超类型。
答案 3 :(得分:1)
两个签名在权力方面是等价的 - 对于任何一组参数,如果存在适用于其中一个的类型参数的选择,则存在可用于另一个的类型参数的选择,并且反之亦然。
您只是在编译器中遇到有限的推断。只需明确指定所需的类型参数:
YourClass.<Vehicle>selectionSort(arr, myComparator);