可比VS <!-?扩展可比->

时间:2018-09-07 14:37:38

标签: java generics java-8 extends comparable

关于以下代码:

public class Test <T extends Comparable>{
    public static void main(String[] args){
        List<String> lst = Array.asList("abc","def");
        System.out.println(func(lst));
    }
    public static boolean func(List<**here**> lst){
        return lst.get(0).compareTo(lst.get(1)) == 0;
    }
}

为什么要编写“?扩展了Comparable”?在此会编译,为什么不编写“ Comparable”?

提前谢谢。

3 个答案:

答案 0 :(得分:8)

之所以会这样,是因为泛型是不变。即使String 一个Comparable,也意味着:

String s = "";
Comparable c = s; // would work

这些泛型不起作用:

List<Comparable> listC = List.of();
List<String> listS = List.of();

listC = listS; // will fail

无论ComparableString之间是什么关系,这都行不通。

当您将该方法的定义更改为:

public static boolean func(List<? extends Comparable> lst) {
    ...
}

这是说:具有扩展绑定的通配符使类型为协变。

这意味着:

List<? extends Comparable> listC = List.of();
List<String> listS = List.of();

listC = listS; // would work here

或更简单地说,它表示List<String> List<? extends Comparable>的子类型

现在要付出很小的代价,因为listC现在是元素的生产者,这意味着您可以从元素中取出元素,但不能在其中放入任何东西。

很容易理解之后,您还没有做完,因为当这样编写时,该方法的定义是完全正确的:

 public static <T extends Comparable<? super T>> boolean func(List<T> lst) {
      .....
 }

答案 1 :(得分:1)

这是因为无法将List<SubClass>强制转换为List<BaseClass>。让我们假设它可以

List<String> sList = new ArrayList<>();
List<Comparable> cList = (List<Comparable>) sList;
cList.add(5);

这将是一个问题,因为整数5不是String,并且不应放在List<String>中。

通过使用? extends Comparable,您是说该函数可以获取具有Comparable作为基类的所有内容的列表(例如List<Comparable>List<String>List<Integer>等)

要更正确地定义函数,您应该执行以下操作:

public static <T extends Comparable<T>> boolean func(List<T> lst) {}

这将强制类型与其自身具有可比性。您的函数会比较列表中的第一个元素和第二个元素,因此最好确保列表中的每个元素实际上都与其他元素具有可比性。

答案 2 :(得分:0)

因为

List<String> lst = Array.asList("abc","def");

lst列表具有通用类型String,而不是ComparableString类,更完善,实现了Comparable<String>接口,因此它适合于? extends Comparable泛型类型。