6

所以我正在阅读通用方法,我很困惑。我先在这里说明问题:

在此示例中:假设我需要一个适用于任何类型 T 的 selectionSort 版本,方法是使用调用者提供的外部可比较。

第一次尝试:

public static <T> void selectionSort(T[] arr, Comparator<T> myComparator){....}

假设我有:

  • 定义的车辆类别
  • 创建了实现 Comparator 的 VehicleComparator,同时按价格比较车辆。
  • 创建卡车扩展车辆
  • 实例化 Truck[] arr ; 车辆比较器 myComparator

现在,我这样做:

selectionSort(arr, myComparator);

并且它不起作用,因为 myComparator 不适用于任何 Vehicle 子类。

然后,我这样做:

public static <T> void selectionSort(T[] arr, Comparator<? super T> myComparator){....}

这个声明会起作用,但我不完全确定我一直在做什么......我知道使用是要走的路。如果“?super T”的意思是“T的未知超类型”,那么我是在施加上限还是下限?为什么超级棒?我的意图是让 T 的任何子类使用 myComparator,为什么是“?super T”。如此困惑...如果您对此有任何见解,我将不胜感激。

提前谢谢!

4

4 回答 4

5

首先,您可以通过Vehicle[]添加Trucks 来解决它。

您需要的原因<? super T>可以追溯到Comparator<Truck>不是Comparator<Vehicle>;子类型的泛型规则。无界类型T必须完全匹配,但事实并非如此。

为了Comparator传入合适的 a,它必须是Comparator被比较的类或其任何超类的 a,因为在 OO 语言中,任何类都可以被视为超类的实例。Comparator因此,只要它是数组组件类型的超类型,它的泛型类型是什么并不重要。

于 2013-12-10T15:12:04.740 回答
4

奇怪的短语? 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);
于 2013-12-10T15:07:56.633 回答
2

你的方法签名

public static <T> void selectionSort(T[] arr, Comparator<? super T> myComparator)

意味着如果您使用类型数组调用它,则T还必须提供Comparator类型 T 或超类型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>并且 aTruck等于数组的类型Truck
  • VehicleComparator实现Comparator<Vehicle> 并且 aVehicle是数组类型的超类型Truck

这将不起作用

selectionSort(trucks, new BigTruckComparator());

因为 aBigTruckComparator是 aComparator<BigTruck>并且 aBigTruck不是数组 type 的超类型Truck

于 2013-12-10T15:22:58.107 回答
1

这两个签名在权力方面是等价的——对于任何一组参数,如果存在适用于其中一个的类型参数的选择,则存在适用于另一个的类型参数的选择,反之亦然。

您只是在编译器中遇到有限的推理。只需显式指定所需的类型参数:

YourClass.<Vehicle>selectionSort(arr, myComparator);
于 2013-12-13T10:29:48.953 回答