0

我明白那个

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?如果它不能推断出 ClassB(实际上推断出 ClassC),那么下面的方法签名(没有“List”)不是等价的吗?

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

谢谢,杰克

4

3 回答 3

5

首先,? extends Object不增加任何值,因为一切都扩展了 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)

他们是不一样的。

原因是,使用第二种方法,您可以传入一个类型为返回类型的子类的 List,而在第一种方法中,List 的类型必须与返回类型的类型相同

于 2012-08-25T13:27:40.833 回答
0

类型推断的工作T方式总是会推断为您调用函数的列表的类型参数,因此<? extends T>永远不会使用 by 提供的额外自由。您可以编写List<T>相同的结果。

回答波西米亚提出的更微妙的观点,推断的类型也可以分配给任何超类型,因此更长的签名再一次没有增加灵活性。

于 2012-08-25T13:26:51.617 回答
0

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实现 aComparable并且您可以返回,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主体内的只读findMax列表TT除了null.
如果您声明List<T> myList,那么它不是一个只读列表,并且可以在您的列表中添加元素,例如在findMax您可以做的内部:这对于asmyList.add(myList.get(0));的声明是不可能的findMaxList<? extends T> myList

于 2012-08-25T13:35:32.383 回答