0

我对下面的代码有疑问。

你能告诉我为什么编译器拒绝接受 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());
        }
    }
4

3 回答 3

2

你误解了什么? super B意思。这意味着它是一个类,在编译时是未知的,B或者是B. 编译器只知道B可以添加对象,毕竟它可能是一个ArrayList<B>. 所以它必须不允许添加A.

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

于 2013-10-10T18:44:35.817 回答
1

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

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

ArrayList原始列表声明的问题是,编译器不知道List<? super B>. 例如,考虑所有类型的列表都可以通过以下方式捕获转换List<? super B>

  • List<A>=>A是超类B
  • List<B>=>? super B可以捕获B
  • List<Object>=>Object是超类B

因此,添加 anew A()可能在第一个和第三个列表中有效,但对List<B>. 这就是为什么编译器不允许您添加new A(). 但是,将列表声明为List<? super A>可以正常工作。但是,再次使用List<A>,这就是您想要的。

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


参考:

于 2013-10-10T18:47:48.510 回答
1

? 在这种情况下是一个存在量词,而不是一个全称。 List< ? super B >应读作for some unknown T such that B <: T, List< T >. 这意味着您只能添加B实例,或者矛盾的是,只能添加 的任何子类B,例如C实例。

于 2013-10-10T19:00:34.823 回答