泛型基础知识

时间:2013-03-04 11:57:31

标签: java generics

为什么以下不起作用?

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

我收到编译错误:

  

方法add(捕获#1-of?extends SomeClass)在类型中   矢量不适用于   arguments(SomeClass)

4 个答案:

答案 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中阅读了这种类型的噱头。