为什么以下不起作用?
Vector<? extends SomeClass> v = new Vector<SomeClass>();
SomeClass e = new SomeClass();
v.add(e);
我收到编译错误:
方法add(捕获#1-of?extends SomeClass)在类型中 矢量不适用于 arguments(SomeClass)
答案 0 :(得分:4)
从某个类型扩展的generic wildcards的集合不允许您添加到Collection
。
由于编译器并不确切知道您尝试添加的SomeClass
类型,因此它不允许。例外情况是null
对象,它可以表示任何类型的Object
。
回答你的评论:虽然你不能添加到Collection
,但它不能被描述为只读,因为它仍然可以删除 Objects
。
要允许添加Objects
,您需要使用已知类型:
Vector<SomeClass> v = new Vector<SomeClass>();
答案 1 :(得分:3)
问题基本上是通过将v
声明为Vector<? extends SomeClass>
,你说它是SomeClass
或其中一个子类的集合。编译器无法对容器实际持有的特定类型做出任何假设,即使new Vector<SomeClass>()
的赋值是在同一行上完成的。尽管编译器知道v
可能已创建为new Vector<SubClassOfSomeClass>()
。这就是为什么它拒绝将 SomeClass
实例(或其他任何事情)放到集合中。但是,您可以获取 SomeClass
元素。
如果您希望将元素添加到集合中,请将v
声明为Vector<? super SomeClass>
,您可以通过该SomeClass
表示它是{{1}的容器} 或其中一个超类。然后编译器知道SomeClass
实例肯定适合这样的集合
但是,您不能从该集合中获取一个SomeClass
元素,因为编译器对其中的元素类型一无所知(除了它是SomeClass
的某个超类)。根据{{1}}的定义,它可能只是v
s的集合。
这简称为 put / get原则,在this等其他帖子中也会详细讨论。
答案 2 :(得分:1)
这解释为here。这样声明的列表实际上是一个只读列表,但它比普通的List<AbstractClass>
列表更灵活。
如果您想将抽象类用作模板,请直接使用它:List<SomeClass> list
。
考虑阅读Java language specification,有很多关于泛型逻辑的信息。
答案 3 :(得分:-1)
在您的问题解释中,您应该没有问题。我理解你的问题,如下面的代码所示。
import java.util.*;
class Test
{
int x;
}
public class Demo
{
public static void main(String args[])
{
Vector<Test> vect = new Vector<Test>();
Test t1 = new Test();
Test t2 = new Test();
t1.x = 10;
t2.x = 20;
vect.add(t1);
vect.add(t2);
for(Test t : vect)
{
System.out.println(t.x);
}
}
}
我在Vector Play With中阅读了这种类型的噱头。