java - 试图理解 super 通配符在 Java 泛型中的作用

标签 java generics extends super

我正在浏览 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> .因此,TGenericMethod里面类应该接受 ClassB 的所有类延伸。

为什么 add方法抛出编译时错误呢?方法不应该 add已经知道它正在传递一个完全兼容的类型?

最佳答案

? super子句是下限通配符。但界限是在推断的类型参数上,而不是对可以传递给采用该泛型类型参数的方法的参数类型的限制。

当你说 <? super ClassB> , 你表示类型参数可以是 ClassB或任何父类(super class)型,例如ClassAObject .

编译器必须处理 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/

相关文章:

java - 如何扩展或实现类?

java - 如何使用用户定义的字段编写自定义异常?

java - 在单元测试中验证 Set 值的最佳方法是什么?

java - 在进行批量更新时,PostUpdate Hook 不起作用

generics - Rust 中的谓词是什么?

java - 将字段添加到 Clojure 中的代理类

java - 在 JSF 中使用 h :inputFile and javax. servlet.http.Part 上传之前验证文件

java - 为什么Java方法参数可以显式协变?

postgresql - Slick 2.0 通用 CRUD 操作

java - super()的使用;在 java