<? extends T>:存储的是T或者T的子类
那么根就是T了(上限),由于存储的是T/T子类,所以具体的类型是不确定的(因为不知道存储的是哪一种具体子类),但是里面的类型肯定是属于T基类类型的(因为存储的不管是什么子类类型,都是可以强转为基类的)。从以上分析可以得知,<? extends T>无法往里面存储数据(不知道要存储哪种子类类型),但是可以往里面获取数据(都是T基类类型)。
<? super T>:存储的是T或者T的基类
那么根就是T了(下限),由于存储的都是T/T基类,因此,可以往里面存任意T的子类型(但是不能存储T的基类型,因为T基类有很多种,不能确定是存储哪一种,这种情况跟<? extends T>不能进行add的操作原因是一样的,只是super无法确定存储哪种基类,extends无法确定存储的是哪种子类),获取元素时,由于存储的是T/T基类,无法确定获取的是哪种具体基类类型,所以是无法进行数据获取的(其实获取是可以的,但是获取 到的都是Object类型)。
举例
比如现有一个篮子(集合),篮子里面可以盛放各种水果:
class Fruit{}
class Apple extends Fruit{}
class Orange extends Fruit{}
class Banana extends Fruit{}
class RedOrange extends Orange{}
class GoldenOrange extends Orange{}
那么:
<? extends Orange >
存放的可能是RedOrange
,GoldenOrange
等等中的特定一种,所以在没掀开篮子遮布前,我无法确定篮子放的是具体哪种水果,所以无法进行存(add
)操作(因为不知道要存哪种Orange
)。但是,就算是闭着眼睛从篮子里拿出一个东西,我肯定知道拿出的是Orange
(不管拿出来的是RedOrange
,GoldenOrange
还是什么,反正都是Orange
),所以取(get
)操作可行。
<? super Orange>
存放的可能是Orange
,Fruit
中的特定一种,所以在没掀开篮子遮布前,我无法确定篮子放的是具体哪种水果,所以无法进行取(get
)操作(有可能拿出来的是Orange
,有可能是Fruit
)。但是,只要是往里面存放Orange
类型水果,那么是绝对是可以的(因为篮子里面的是Orange
或者Fruit
中特定水果,那么RedOrange
和GolenOrange
也是属于Orange
和Fruit
呀)。
总结
<? extends T>
可以获取数据(get T类型),无法存储数据(add)。
<? superT>
可以存储数据(add T及T的子类),无法获取数据(get)。
什么时候要使用<? extends T>
,<? super T>
呢,请记住下面这句话:
- 如果你是希望调用T方法,那么使用
<? extends T>
,因为你可以进行取操作(get
)。 - 如果你是希望往容器里面存数据,那么使用
<? super T>
。