为什么我不能将 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(); }
由于以下原因:
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
简短的解释:
<? extends A>
的意思是:扩展A
的一些特定但未知的类型。 可以是A
本身或其任何亚型。 因此,不能在此集合中插入任何元素:编译器无法知道 add(object)
方法的参数哪种类型是合法的。
请记住:提供程序扩展使用者超级(也称为 PECS(
您希望将内容放入集合中,因此集合是使用者。
Collection<? super A> collection = new ArrayList<A>();
从这个答案
情况 2:您想要向集合中添加内容。 那么列表就是一个消费者,所以你应该使用一个
Collection<? super Thing>
。这里的推理是,与
Collection<? extends Thing>
不同,无论实际的参数化类型是什么,Collection<? super Thing>
总是可以保存Thing
。在这里,您不关心列表中已有的内容,只要它允许添加Thing
;这就是? super Thing
保证的。
如果你有<? extends A>
那么此时编译器不知道正在使用的A
子类是什么。因此,将除 null
之外的任何对象添加到集合中都是不安全的。
不能向List<? extends T>
添加任何对象,因为无法保证它真正指向的列表类型,因此无法保证该对象允许在该列表中。唯一的"保证"是你只能从中阅读,你会得到一个T
或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
因此我们可以读取它,因为我们可以将子类的实例分配给父类引用。