Java数组sort方法类型边界:Comparator<? super T>与<T>的差异示例
示例:
Arrays.sort 两种泛型声明的差异 先明确两个方法声明:
可正常运行的声明:
public static <T> void sort(T[] a, Comparator<? super T> c)
无法适配场景的声明:
public static <T> void sort(T[] a, Comparator<T> c)
具体场景代码
首先定义类结构:
class Animal { private String name; public Animal(String name) { this.name = name; } public String getName() { return name; } } class Dog extends Animal { public Dog(String name) { super(name); } }
然后创建一个针对Animal的比较器:
// 用于比较Animal及其子类的比较器 Comparator<Animal> animalNameComparator = (a1, a2) -> a1.getName().compareTo(a2.getName());
两种声明的调用差异
- 使用带
<? super T>的声明:
Dog[] dogs = {new Dog("Buddy"), new Dog("Max"), new Dog("Charlie")}; // 完全可行:Comparator<Animal>是Comparator<? super Dog>的子类型 sort(dogs, animalNameComparator);
这里T被推断为Dog,Comparator<? super Dog>可以接受Comparator<Animal>(因为Animal是Dog的父类),所以编译通过,运行正常。
- 使用仅
Comparator<T>的声明:
Dog[] dogs = {new Dog("Buddy"), new Dog("Max"), new Dog("Charlie")}; // 编译报错:Comparator<Animal>无法转换为Comparator<Dog> sort(dogs, animalNameComparator);
此时T推断为Dog,方法要求传入Comparator<Dog>,但我们只有Comparator<Animal>,而泛型是不可协变的——Comparator<Animal>不是Comparator<Dog>的子类,所以编译失败。
原理说明
这是泛型中PECS原则的典型应用:当我们需要消费(接收)类型T的对象时,应该使用? super T(Producer Extends, Consumer Super)。比较器在比较T类型对象时,只需要能接收T或其父类的对象即可,所以用? super T可以让比较器的适用范围更广,支持父类比较器操作子类数组的场景,而仅用Comparator<T>会限制只能使用同类型的比较器,灵活性大打折扣。
内容的提问来源于stack exchange,提问作者VS228
相关产品推荐
相关产品推荐

