我正在浏览 this文章了解super
的作用泛型中的通配符。我了解如何 extends
有效,但我很难理解 super
我有一个 ClassA
这是由ClassB
扩展 , 制作 ClassA
父类(super class)ClassB
.
如果我对文章的理解正确,<? super ClassB>
将允许任何属于 ClassB
的父类(super class)型的类.
我有以下代码
通用方法.java
public class GenericMethod<T> {
private List<T> list;
public GenericMethod() {
list = new ArrayList<>();
}
public void add(T t) {
list.add(t);
}
public T get(int index) {
return list.get(index);
}
}
Driver.java
public class Driver {
public static void main(String[] args) {
GenericMethod<? super ClassB> genericMethod = new GenericMethod<>();
ClassA classA = new ClassA();
genericMethod.add(classA); // Compile-time error here
}
}
错误
The method add(capture#1-of ? super ClassB) in the type GenericMethod<capture#1-of ? super ClassB> is not applicable for the arguments (ClassA)
我不明白我哪里错了。当我实例化 GenericMethod
类,我已经声明它会接受属于 ClassB
的父类(super class)型 的任何值与声明 <? super ClassB>
.因此,T
在GenericMethod
里面类应该接受 ClassB
的所有类延伸。
为什么 add
方法抛出编译时错误呢?方法不应该 add
已经知道它正在传递一个完全兼容的类型?
最佳答案
? super
子句是下限通配符。但界限是在推断的类型参数上,而不是对可以传递给采用该泛型类型参数的方法的参数类型的限制。
当你说 <? super ClassB>
, 你表示类型参数可以是 ClassB
或任何父类(super class)型,例如ClassA
或 Object
.
编译器必须处理 add
方法就好像它可以是这些签名中的任何一个一样:
add(Object t)
add(ClassA t)
add(ClassB t)
(如果 ClassA
直接从另一个类而不是 Object
继承,则可能有其他类型)。
编译器必须拒绝 ClassA
作为 add
的参数因为类型参数可以推断为 ClassB
.分配 GenericMethod<ClassB>
是合法的给你的genericMethod
变量。
GenericMethod<? super ClassB> genericMethod = new GenericMethod<ClassB>();
但是能够传递一个ClassA
是没有意义的到一个需要 ClassB
的方法.
事实上,这就是钻石运算符的推断 - ClassB
.
您混淆了两个概念:在使用类型参数的方法中允许使用什么类型的参数以及允许使用什么类型的对象。使用通配符限制类型参数,但该方法仍然接受作为类型参数或子类型的类型。
关于java - 试图理解 super 通配符在 Java 泛型中的作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58420734/