java通用和<;中的通配符;?超级T>;下界或上界

java通用和<;中的通配符;?超级T>;下界或上界,java,generics,wildcard,extends,bounded-wildcard,Java,Generics,Wildcard,Extends,Bounded Wildcard,所以我正在读关于泛型方法的书,我感到困惑。让我先在这里说明问题: 在本例中:假设我需要一个适用于任何类型T的selectionSort版本,方法是使用调用者提供的外部可比函数 第一次尝试: public static <T> void selectionSort(T[] arr, Comparator<T> myComparator){....} 它不会工作,因为myComparator不适用于车辆的任何子类 然后,我这样做: public static <T&g

所以我正在读关于泛型方法的书,我感到困惑。让我先在这里说明问题:

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

第一次尝试:

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

它不会工作,因为myComparator不适用于车辆的任何子类

然后,我这样做:

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

publicstaticvoidselectionsort(T[]arr,Comparator这个带有疑问的短语
?super T
意味着目标列表可以包含任何类型的元素 这是
T
的超类型,就像源列表可能包含任何类型的元素一样
T的子类型

我们可以从
集合
中看到非常简单的示例
复制

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));
   }
}

public static void copy(列表首先,您可以通过将
Vehicle[]
添加到
Truck
来解决此问题

需要方法签名的原因

public static <T> void selectionSort(T[] arr, Comparator<? super T> myComparator)
这样就行了

Truck[] trucks = ...;
selectionSort(trucks, new TruckComparator());
selectionSort(trucks, new VehicleComparator());
因为

  • TruckComparator
    实现
    Comparator
    ,并且
    Truck
    等于数组的类型
    Truck
  • VehicleComparator
    实现
    比较器
    ,而
    车辆
    是阵列类型
    卡车的超级类型
这将不起作用

selectionSort(trucks, new BigTruckComparator());

因为
bigtrackcomparator
是一个
比较器
,而
bigtrack
不是数组类型的超级类型
Truck

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

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

YourClass.<Vehicle>selectionSort(arr, myComparator);
YourClass.selectionSort(arr,myComparator);

这将对您有所帮助。这应该对您有用,这也可能对您有所帮助。有效的Java书籍建议您记住这一点-PECS(生产者
扩展
,消费者
超级
)。使用
extends
生成类,使用
super
生成消费类。@PrasadKharkar非常感谢!博客已经准备好了,里面甚至有一个例子!“但它不起作用,因为myComparator不适用于车辆的任何子类。”这是错误的。
myComparator
比较
车辆
,是的。
Truck[]
车辆【】
。如果我错了,请纠正我。。所以“?超级T”可以是上界也可以是下界,这取决于我把这个短语放在哪里,对吗?
super
是下界,当
extends
是上界时,但是谁说
T
Truck
?如果你选择
T
作为
Vehicle
,那么它就起作用了。@newacct如果你仔细阅读了wuestion,哟你会看到他实例化了
Truck[]arr
,然后将其传递给
T[]
,因此java将
T
推断为
Truck
。这是毫无疑问的。当然,他的编译器可能是这样推断的。但是如果推断不足,他总是可以手动提供类型参数。你说“您需要
+1,但值得一提的是,这仅是因为数组是协变的(
Truck[]
Vehicle[]
)。如果该方法采用的是
列表
,则使用
比较器
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());
selectionSort(trucks, new BigTruckComparator());
YourClass.<Vehicle>selectionSort(arr, myComparator);