可比较接口 VS <? extends Comparable>泛型限定

4
有关以下代码:
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"则无法编译通过。为什么呢?谢谢!
3个回答

8
这是因为泛型是不变的。即使“String”本身是“可比较的”(Comparable),也无法调用其compareTo方法,因为它不是作为泛型类型参数声明的。
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) {
    ...
}

据说:使用extends-bound的通配符使类型协变。

这意味着:

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`无法转换为`List`。假设它可以转换:
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,而不是Comparable

String类实现了Comparable<String>接口,因此它适合于? extends Comparable通用类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接