我想弄清楚为什么我不能在泛型方法声明中使用super
?看下面的例子,它没有编译,但我不确定原因。
public class A<E> {
public <T extends A> void test1(T t) { // Compiles fine
}
public <T super A> void test2(T t) { // Compilation error??
}
public <T super A> <T> void test3(T t) { // Compilation error??
}
}
class A {}
....
答案 0 :(得分:2)
类型参数和类型参数之间存在差异。通配符(super
和extends
)的使用用于类型参数,也就是说,当您实际定义类型参数的相应值时,在调用站点声明它们。或者,关键字extends
可用于类型参数约束。
因此,在定义class List<T>{}
中,T
被称为类型参数。当您声明类型List
的引用时,在调用站点,您可以为T
提供类型参数,该参数可以是不变量(即List<String> jedis
)或通配符超级或有扩展(即List<? extends Number> myNums
,List<? super String> names
)。
关键字extends
也可以用于完全不同的目的,以声明给定类型参数的约束。例如,声明:
class List<T extends CharSequence>{}
类型参数T
受到约束。这意味着每当您为类型参数T
声明类型参数时,它必须是CharSequence
类型或其任何子类型。
因此List<String>
将是有效声明,但List<Integer>
不会。
在类型参数约束的声明中不允许使用关键字super
,这可能是因为它在您的声明中没有多大意义,可能是{{1的有效类型参数那不是T
本身?
答案 1 :(得分:2)
考虑一下,如果方法可以有签名
public <T super A> void test2(T t) {
}
然后它可以将任何对象作为参数。为什么?因为,例如,您始终可以将T
推断为Object
(Object
是A
的超类型),并且任何对象都是Object
的实例,所以它有效。因此以这种方式声明它将是非常多余的。你可以写
public void test2(Object t) {
}
同样的效果。