2

为什么以下不起作用?

Vector<? extends SomeClass> v = new Vector<SomeClass>();  
SomeClass e = new SomeClass();  
v.add(e);  

我收到一个编译错误:

Vector 类型中的方法 add(capture#1-of ? extends SomeClass) 不适用于参数 (SomeClass)

4

4 回答 4

4

具有从一个类型扩展的通用通配符的集合不允许您添加到该类型Collection

由于编译器不知道您要添加的确切类型SomeClass因此它不允许添加。一个例外是null可以表示任何类型的Object.

回答您的评论:虽然您无法添加Collection,但不能将其描述为只读,因为仍然可以删除 Objects

要允许添加Objects,您需要使用已知类型:

Vector<SomeClass> v = new Vector<SomeClass>();
于 2013-03-04T12:00:17.263 回答
3

问题基本上是通过声明它是一个集合v的一个子类。编译器无法对容器实际保存的特定类型做出任何假设,即使分配是在同一行上完成的。据编译器所知,可能已创建为. 这就是为什么它拒绝实例(或其他任何东西)放入集合中。但是,您可以从中获取元素。Vector<? extends SomeClass>SomeClass new Vector<SomeClass>()vnew Vector<SubClassOfSomeClass>() SomeClassSomeClass

如果您希望能够元素放入集合中,则声明vVector<? super SomeClass>,这样您就可以说它是容器SomeClass 或其超类之一。然后编译器知道一个SomeClass实例肯定适合这样的集合。
但是,您不能从该集合中获取元素SomeClass,因为编译器对其中元素的类型一无所知(除了它是 的某个超类SomeClass)。根据它的定义,v它也可能只是Objects 的集合。

这被称为put/get 原则,在其他类似帖子中也有详细讨论。

于 2013-03-04T12:10:46.410 回答
1

这是解释here。这样声明的列表实际上是一个只读列表,但它比普通List<AbstractClass>列表更灵活。

如果您想使用抽象类作为模板,只需像这样直接使用它:List<SomeClass> list.

考虑阅读Java 语言规范,有很多关于泛型逻辑的信息。

于 2013-03-04T12:00:32.793 回答
-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中读到了这种类型的噱头。

于 2013-03-04T12:26:52.883 回答