超级通配符导致的编译错误

时间:2013-10-10 18:42:26

标签: java generics arraylist wildcard super

我对以下代码有疑问。

你能告诉我为什么编译器拒绝接受ty.add(new A());?毕竟A是B的超类(即,符合要求)。

错误消息如下:

C.java:15: error: no suitable method found for add(A)
                ty.add(new A());
                  ^
    method List.add(int,CAP#1) is not applicable
      (actual and formal argument lists differ in length)
    method List.add(CAP#1) is not applicable
      (actual argument A cannot be converted to CAP#1 by method invocation conversion)
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Object super: B from capture of ? super B
1 error

这是代码(C.java):

import java.util.ArrayList;
import java.util.List;

class A
    {
    }
class B extends A
    {
    }
class C extends B
    {
    public static void main(String args[])
        {
        List<? super B> ty = new ArrayList<A>();
        ty.add(new A());
        ty.add(new B());
        ty.add(new C());
        }
    }

3 个答案:

答案 0 :(得分:2)

你误解了? super B的含义。这意味着它是一个在编译时未知的类,即B或超级类B。编译器只知道可以添加B个对象,毕竟它可能是ArrayList<B>。因此,必须禁止添加A

要允许添加A,请考虑List<? super A>List<A>类型ty

答案 1 :(得分:1)

好吧,如果您只想添加子类对象,那么只需将列表声明为:

List<A> list = new ArrayList<A>();
list.add(new A());  // fine
list.add(new B());  // fine

原始列表声明的问题是,编译器不知道ArrayList引用的实际List<? super B>类型是什么。例如,考虑List<? super B>所有类型的列表 capture-convertible

  • List<A> =&gt; AB
  • 的超类
  • List<B> =&gt; ? super B可以捕获B
  • List<Object> =&gt; ObjectB
  • 的超类

因此,添加new A()可能在第1和第3个列表中有效,但它对List<B>无效。这就是编译器不允许您添加new A()的原因。但是,将列表声明为List<? super A>可以正常工作。但是,再次选择List<A>,这就是你想要的。

创建类似 - List<? extends X>List<? super X>的列表的重点是允许您将List<E>的不同具体参数化实例化绑定到单个引用。


<强>参考文献:

答案 2 :(得分:1)

?在这种情况下,是一个存在量词,而不是一个普遍的量词。 List< ? super B >应该被理解为for some unknown T such that B <: T, List< T >。这意味着您只能添加B个实例,或者矛盾地添加B的任何子类,例如C个实例。