首页 > 解决方案 > 将超类对象放入下界通配符列表时出错

问题描述

我知道在列表上使用下限通配符作为方法参数应该让我们放置该下限及其超类型的元素,但请考虑以下代码:

public class WildcardError {
    void foo(List<? super Number> i) {
        i = new ArrayList<Integer>(); //compile error
        i.add(new Integer(2)); // no error
    }
}

现在在这里我明白为什么在方法 foo 的第一个语句中存在编译错误,因为 Integer 的 ArrayList 不是“?super Number”的 List 的子类型,但是为什么我们允许将 Integer 放入此列表中,即使 integer 不是Number 的超类型?在以下代码中也是相反的:

public class WildcardError {
    void foo(List<? super Integer> i) {
        i = new ArrayList<Number>(); //no error
        Number k =20;
        i.add(k); // compile error
    }
}

在这里,我知道语句 2 中应该没有编译错误,因为 Number 的 ArrayList 是“?super Integer”列表的子类型,但为什么最后一条语句出现编译错误?

虽然 ?super Integer 应容纳超类 Number。

我试图找到答案,但无法搜索确切的场景。

标签: javagenericsbounded-wildcard

解决方案


在第一个示例中,下限? super Number意味着实际类型参数可以是Number或者是超类型(例如Object)。因为 Java 的泛型是不变的,所以 aList<? super Number>不能匹配ArrayList<Integer>. 请记住,下限是类型参数的界限,而不是可能作为参数发送的参数类型的界限。调用没有错误,add因为Integer可以将 an 传递给add可能采用 aNumber或超类的方法。

在第二个示例中,下限? super Integer意味着实际的类型参数可以是Integer或者是超类型(例如Number, Object)。这匹配ArrayList<Number>,所以这里没有错误。但是,typei仍然List<? super Integer>是 ,不保证可以取Number比如k。它可以在任何时候指List<Integer>一个NumberDouble应该被接受的地方。这就是这里出现编译器错误的原因。


推荐阅读