0

为什么我不能将 a 对象添加到集合中?因为 B 类是扩展 A 的东西。

import java.util.*;

public class TestGeneric
{
  public static void main(String[] args)
  {
    Collection<? extends A> collection = new ArrayList<A>();
    A a = new B();
    collection.add(a);
  }

  private static class B implements A {
    public int getValue() { return 0; }
  }
}

interface A { int getValue(); }
4

4 回答 4

4

由于以下原因:

Collection<? extends A> coll = new ArrayList<C>(); // C extends A

coll.add(new B()); // B extends A, but doesn't extend C. Oops.

但是,由于编译器知道 coll 仅具有扩展 A 的元素,因此您仍然可以将它们检索为 As。

A myA = coll.get();  // No problem, it might be B or C, but they both extend A
于 2013-09-24T12:12:53.967 回答
3

简短的解释:

<? extends A>意思是:一些特定但未知的扩展类型A。可以是A它自己或它的任何子类型。因此,您不能在此集合中插入任何元素:编译器无法知道该方法的参数的合法类型add(object)

于 2013-09-24T12:51:31.773 回答
2

请记住:提供者扩展了消费者超级(也称为 PECS)

您想东西放入集合中,因此集合是消费者

    Collection<? super A> collection = new ArrayList<A>();

这个答案

案例 2:您想将东西添加到集合中。那么这个列表就是一个消费者,所以你应该使用一个Collection<? super Thing>.

这里的原因是,无论实际的参数化类型是什么,与 , 不同Collection<? extends Thing>Collection<? super Thing>都可以始终持有 a 。Thing在这里,您不必关心列表中已有的内容,只要允许Thing添加 a 即可;这就是? super Thing保证。

于 2013-09-24T12:14:03.620 回答
1

如果你有<? extends A> 那么此时编译器不知道正在A使用的子类是什么。因此,将任何对象添加到集合中是不安全的,除了null.

您不能向其中添加任何对象,List<? extends T>因为您无法保证它真正指向的是哪种列表,因此您无法保证该对象在该列表中是允许的。唯一的“保证”是你只能从中读取,你会得到一个Tor subclass of T

List<? extends Number>可以通过三个实现:

List<? extends Number> list = new ArrayList<Number>(); // 数字“扩展”数字 List<? extends Number> list = new ArrayList<Integer>();// 整数扩展数字 List<? extends Number> list = new ArrayList<Double>(); // 双精度扩展数字

因此,如果是new ArrayList<Double>()并且您正在添加integer,那么这是一个错误,因此编译器将访问限制为仅读取不添加是安全的。

添加也是安全的,因为我们知道父类,因此我们可以将任何子类分配给父类引用,如下所示:

Parent p = new Child();//这是安全的

因此,List<? extends Number> 我们知道集合中的所有元素都在以某种方式扩展,Number因此我们可以读取它,因为我们可以将子类的实例分配给父类引用。

于 2013-09-24T12:17:23.120 回答