我明白
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){
谢谢,杰克
3条答案
按热度按时间pieyvz9o1#
首先,
? extends Object
不添加任何值,因为everything扩展了object,所以这两个方法是等效的:经过简化,你的问题基本上是这些等价物:
它们(不)是一样的。
原因是,在第二个方法中,可以传入一个类型为返回类型的子类的列表,而在第一个方法中,列表的类型必须与返回类型的类型相同。
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
ss2ws0br3#
类型推断的工作方式,
T
总是推断为调用函数的列表的类型param,因此<? extends T>
永远不会被使用。你可以写List<T>
同样的结果。为了回答波希米亚人提出的更微妙的问题,推断的类型也可以赋给任何超类型,因此较长的签名再次没有增加灵活性。