关键在于引用和实例之间的差异,以及引用可以承诺的内容以及实例真正可以执行的操作。
ArrayList<A> a = new ArrayList<A>();
下面是对特定类型的实例的引用 - 正好是 s 的数组列表。更明确地说,是对数组列表的引用,该数组列表将接受 s 并生成 s。 是 s 的数组列表的实例,即接受 s 并生成 s 的数组列表。a
A
a
A
A
new ArrayList<A>()
A
A
A
ArrayList<Integer> a = new ArrayList<Number>();
这里,是对 的数组列表的引用,即恰好是一个可以接受 s 并生成 s 的数组列表。它不能指向 s 的数组列表。s 的数组列表不能满足 的所有承诺(即,数组列表 s 可能会生成不是 s 的对象,即使它当时是空的)。a
Integers
Integer
Integer
Number
Number
ArrayList<Integer> a
Number
Integer
ArrayList<Number> a = new ArrayList<Integer>();
在这里,声明 of that 将恰好引用 s 的数组列表,即恰好是一个将接受 s 并生成 s 的数组列表。它不能指向 s 的数组列表,因为 的类型声明 say 可以接受任何 ,但 s 的数组列表不能只接受任何 ,它只能接受 s。a
a
Number
Number
Number
Integer
a
a
Number
Integer
Number
Integer
ArrayList<? extends Object> a= new ArrayList<Object>();
下面是对一组类型的(泛型)引用,而不是对特定类型的引用。它可以指向属于该家庭的任何列表。但是,这个很好的灵活引用的权衡是,如果它是特定于类型的引用(例如非泛型),它们无法承诺所有功能。在本例中,是对将生成 的数组列表的引用。但是,与特定于类型的列表引用不同,此引用不能接受任何 .(即,并非可以指向的类型家族中的每个成员都可以接受任何,例如,s的数组列表只能接受s。a
a
Object
a
Object
a
Object
Integer
Integer
ArrayList<? super Integer> a = new ArrayList<Number>();
同样,是对一系列类型(而不是单个特定类型)的引用。由于通配符使用 ,此列表引用可以接受 s,但不能生成 s。换句话说,我们知道,可以指向的类型家族的任何和每个成员都可以接受。但是,并非该家族的每个成员都可以产生s。a
super
Integer
Integer
a
Integer
Integer
PECS - 生产者 , 消费者 - 此助记符可帮助您记住,使用意味着泛型类型可以生成特定类型(但不能接受它)。使用意味着泛型类型可以使用(接受)特定类型(但不能生成它)。extends
super
extends
super
ArrayList<ArrayList<?>> a
一个数组列表,它保存对作为数组列表类型系列成员的任何列表的引用。
= new ArrayList<ArrayList<?>>(); // correct
数组列表的一个实例,该实例保存对作为数组列表类型系列成员的任何列表的引用。
ArrayList<?> a
对任何数组列表(数组列表类型系列的成员)的引用。
= new ArrayList<?>()
ArrayList<?>
引用数组列表类型系列中的任何类型,但只能实例化特定类型。
另请参阅如何添加到 List<? 扩展了数字>数据结构?