我对以下代码有疑问。
你能告诉我为什么编译器拒绝接受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());
}
}
答案 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; A
是B
List<B>
=&gt; ? super B
可以捕获B
List<Object>
=&gt; Object
是B
因此,添加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
个实例。