java—在下面的示例中,“list< ”是吗?扩展t>“必要的,或者”list< t>“会做同样的事情吗?

tmb3ates  于 2021-07-09  发布在  Java
关注(0)|答案(3)|浏览(394)

我明白

List<? extends T>

允许列表是t的任何子类型(或t本身),并且

List<T>

只允许类型为t的列表。但是,请查看以下方法签名:

public static <T extends Object & Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end){

以及以下课程:

public class ClassA{

}
public class ClassB extends ClassA implements Comparable<ClassA>{
public int compareTo(ClassA s){
    //do comparison
}
}
public class ClassC extends ClassB{

}

假设t是classb,我想为我的列表传递一个子类型t(classc):

public static void main(String[] args){
    List<ClassC> myC = new ArrayList<ClassC>();
    ClassC a = findMax(myC, 2, 3);
}

在本例中,java如何推断t是classb而不是classc?如果它不能推断类B(实际上是推断类C),那么下面的方法签名(没有“list”)不是等价的吗?

public static <T extends Object & Comparable<? super T>> T findMax(List<T> myList, int begin, int end){

谢谢,杰克

pieyvz9o

pieyvz9o1#

首先, ? extends Object 不添加任何值,因为everything扩展了object,所以这两个方法是等效的:

public static <T extends Object & Comparable<? super T>> T findMax(List<T> myList, int begin, int end)
public static <T extends Comparable<? super T>> T findMax(List<T> myList, int begin, int end)

经过简化,你的问题基本上是这些等价物:

public static <T extends Comparable<? super T>> T findMax(List<T> myList, int begin, int end)
public static <T extends Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end)

它们(不)是一样的。
原因是,在第二个方法中,可以传入一个类型为返回类型的子类的列表,而在第一个方法中,列表的类型必须与返回类型的类型相同。

llycmphe

llycmphe2#

java如何推断t是classb而不是classc?
我不明白你的意思。泛型是一种编译类型技术。
删除 public static <T extends Object & Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end) 是到 Object
这将编译为 public static Object findMax(List myList, int begin, int end) 当您示例化列表时 List<ClassC> myC = new ArrayList<ClassC>(); 并将其传递给方法,编译器确保类型安全,本质上是传递列表符合声明。在这种情况下 Class C 实现 Comparable 你可以回来 Class B 因为编译器会接受它。
泛型在运行时不存在。
评论后更新:
这个 public static <T extends Object & Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end) 不同于: public static <T extends Object & Comparable<? super T>> T findMax(List<T> myList, int begin, int end) 这与类型推断无关。编译器会在这里进行与以前相同的类型推断 T 或者 ? extends T 在这种特殊情况下。
区别在于合同。这个 public static <T extends Object & Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end) 声明一个方法,该方法保证不会修改集合(至少不会损坏它)。
这个 List<? extends T> myList 本质上使list在 findMax 无法在列表中添加任何示例(或者 T 或子类型 T )除外 null .
如果你宣布 List<T> myList 然后它不是一个只读列表,可以在列表中添加元素,例如 findMax 你可以做: myList.add(myList.get(0)); 这是不可能的声明 findMax 作为 List<? extends T> myList

ss2ws0br

ss2ws0br3#

类型推断的工作方式, T 总是推断为调用函数的列表的类型param,因此 <? extends T> 永远不会被使用。你可以写 List<T> 同样的结果。
为了回答波希米亚人提出的更微妙的问题,推断的类型也可以赋给任何超类型,因此较长的签名再次没有增加灵活性。

相关问题