Java方法泛型理解

时间:2012-06-24 02:22:44

标签: java generics

我想弄清楚为什么我不能在泛型方法声明中使用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 {}
....

2 个答案:

答案 0 :(得分:2)

类型参数和类型参数之间存在差异。通配符(superextends)的使用用于类型参数,也就是说,当您实际定义类型参数的相应值时,在调用站点声明它们。或者,关键字extends可用于类型参数约束。

类型参数与类型参数

因此,在定义class List<T>{}中,T被称为类型参数。当您声明类型List的引用时,在调用站点,您可以为T提供类型参数,该参数可以是不变量(即List<String> jedis)或通配符超级或有扩展(即List<? extends Number> myNumsList<? 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推断为ObjectObjectA的超类型),并且任何对象都是Object的实例,所以它有效。因此以这种方式声明它将是非常多余的。你可以写

public void test2(Object t) {
}

同样的效果。