关键在于引用和实例之间的区别,以及引用可以承诺什么,实例真正能做什么。
ArrayList<A> a = new ArrayList<A>()
这里的a
是指特定类型的实例,确切地说,是A
类型的数组列表。更明确地说,a
是一个引用,指向一个可以接受A
并能生成A
的数组列表。而new ArrayList<A>()
则是A
类型的数组列表的一个实例,即一个可以接受A
并能生成A
的数组列表。
ArrayList<Integer> a = new ArrayList<Number>()
在这里,
a
是一个引用,确切地说是一个
Integer
数组列表,即只能接受
Integer
并生成
Integer
的数组列表。它不能指向
Number
的数组列表。那个
Number
的数组列表无法满足
ArrayList<Integer> a
的所有承诺(即一个
Number
的数组列表可能会产生不是
Integer
的对象,即使此时为空)。
ArrayList<Number> a = new ArrayList<Integer>()
在这里,a
的声明表示,a
将指向一个完全由Number
组成的数组列表,也就是说,它将接受Number
并生成Number
。它不能指向Integer
的数组列表,因为a
的类型声明表示,a
可以接受任何Number
,但是Integer
的数组列表不能接受任何Number
,它只能接受Integer
。
ArrayList<? extends Object> a= new ArrayList<Object>()
这里的
a
是对一个类型族的(泛型)引用,而不是对特定类型的引用。它可以指向该族中的任何列表。然而,这种灵活的引用也意味着它不能保证与非泛型引用相同的所有功能。在本例中,
a
是一个引用到将产生
Object
s 的数组列表。但是,与特定类型的列表引用不同,这个
a
引用不能接受任何
Object
。(即
a
可以指向的类型族的成员不能都接受任何
Object
,比如一个由
Integer
组成的数组列表只能接受
Integer
)。
ArrayList<? super Integer> a = new ArrayList<Number>()
再次强调,a
是一组类型的引用(而不是单个特定类型)。由于通配符使用了super
,因此此列表引用可以接受Integer
,但不能生成Integer
。换句话说,我们知道a
可以指向的类型族中的任何成员都可以接受Integer
,但并非该族的每个成员都能生成Integer
。
PECS - 生产者extends
,消费者super
- 这个助记符帮助你记住使用extends
表示泛型类型可以生成具体类型(但不能接受它)。使用super
表示泛型类型可以消费(接受)具体类型(但不能生成它)。
ArrayList<ArrayList<?>> a
一个数组列表,它持有对于任何属于数组列表类型家族的列表的引用。
= new ArrayList<ArrayList<?>>()
一个数组列表实例,它持有对任何属于一组数组列表类型的列表的引用。
ArrayList<?> a
任何数组列表的引用(数组列表类型家族的成员之一)。
= new ArrayList<?>()
ArrayList<?>
是指数组列表类型家族中的任意类型,但你只能实例化一个特定类型。
另请参见如何向 List<? extends Number>
数据结构中添加元素?
a1.add(new Integer(3));
这样的事情吗? - Gabe