可比VS扩展了Comparable>

问题描述 投票:4回答:3

关于以下代码:

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

为什么在这里写“?extends Comparable”会编译,写“Comparable”会不会编译?

提前致谢。

java generics java-8 extends comparable
3个回答
8
投票

这是因为泛型是不变的。即使StringComparable,意思是:

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
投票

这是因为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) {}

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


0
投票

因为

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

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

© www.soinside.com 2019 - 2024. All rights reserved.