为什么我不能将一个对象添加到集合中?因为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(); }
答案 0 :(得分: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
答案 1 :(得分:2)
请记住:Provider extends consumer super(也称为PECS)
您希望将内容添加到集合中,因此该集合是消费者。
Collection<? super A> collection = new ArrayList<A>();
来自this回答
案例2:您想要向集合中添加内容。 然后列表是消费者,因此您应该使用
Collection<? super Thing>
。这里的推理是,与
Collection<? extends Thing>
不同,Collection<? super Thing>
无论实际的参数化类型是什么,都可以始终保持Thing
。这里你不关心列表中已有的内容,只要它允许添加Thing
;这是? super Thing
保证的。
答案 2 :(得分:1)
如果你有<? extends A>
那么此时编译器不知道正在使用的A
的子类是什么。因此,除了null
之外,将任何对象添加到集合中是不安全的。
您无法向List<? extends T>
添加任何对象,因为您无法保证它实际指向的是哪种List,因此您无法保证该列表中允许该对象。唯一的“保证”是您只能从中读取,并且您将获得T
或subclass of T
。
List<? extends Number>
可以由三个实现:
List<? extends Number> list = new ArrayList<Number>();
//数字“extends”数字
List<? extends Number> list = new ArrayList<Integer>();
//整数扩展数字
List<? extends Number> list = new ArrayList<Double>();
// Double extends Number
因此,如果它是new ArrayList<Double>()
并且您正在添加integer
,那么这是一个错误,因此编译器可以安全地将访问限制为仅读取不添加。
添加也是安全的,因为我们知道父类,因此我们可以将任何子类分配给父类引用,如下所示:
Parent p = new Child();
//这是安全的
因此在List<? extends Number>
我们知道集合中的所有元素都以某种方式扩展Number
因此我们可以读取它,因为我们可以将子类的实例分配给父类引用。
答案 3 :(得分:1)
简短而简单的解释:
<? extends A>
表示:扩展A
的某些特定但未知的类型。可能是A
本身或其任何子类型。因此,您无法在此集合中插入任何元素:编译器无法知道add(object)
方法的参数的合法类型。