在下面的例子中,“List <! - ?extends T - >”是必要的,还是“List <t>”做同样的事情?</t>

时间:2012-08-25 13:17:22

标签: java generics wildcard type-bounds

我理解

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){

谢谢, 杰克

3 个答案:

答案 0 :(得分: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的类型必须是相同的类型。返回的类型。

答案 1 :(得分:0)

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

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

答案 2 :(得分: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实现了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本质上使列表成为findMax正文中的只读列表,该列表无法在列表中添加任何实例(TT的子类型除外){ {1}}。
如果您声明null,则它不是只读列表,可以在列表中添加元素,例如在List<T> myList内你可以做到:findMax这是myList.add(myList.get(0));声明为findMax

无法实现的