1.泛型通配符
<? extends T>:是指 “上界通配符”
<? super T>:是指 “下界通配符”
这两种泛型通配符可以解决苹果是水果但装苹果的盘子不是装水果的盘子的问题,同时也带来了限制。
<? extends T>的泛型集合不能使用 add 方法,而 < ? super T> 不能使用 get 方法。
1. 上界通配符<? extends E>的分析
A <? extends E>作为形参时例如List<? extends E>可以使用集合的get方法来获取E或者E类型本身的元素。
`原因分析`:当我们用get方法时我们其实是在获取集合里内部的元素,但是我们的集合的数据类型还没有确定,但是我们可以获得一些明确的已知条件,那就是在<? extends E>中最大的类型是E,而且这个E最大是Object,所以我们可以利用这一点,那么我们就可以清楚地了解到该集合里面的获取的元素肯定是E或者Object的子类,他们的范围肯定小于E或者Object,那么我们就可以用Object和E这两个范围比集合里面的元素大的类去接收集合里面的元素。
B 在使用上界通配符时,无法调用add方法来添加非null的元素。
`原因分析`:由于上面已经说得很清楚了,<? extends E>作为形参时例如List<? extends E>这时最大类型是E和Object,但是我们不清楚最小的类型是什么,因为此时?这个通配符没有被赋值,我们调用add方法是要添加集合元素或者集合元素的子类,但是我们没法明确肯定该集合元素类型,或者比该集合元素范围更小的子类,那么Java就不会允许添加元素。
2. 下界通配符<? super E>的分析
A 在使用下界通配符时,无法使用get方法获取Object以外的元素,或者需要向下转型,但是可能出现ClassCastException的异常。
`原因分析`:上界通配符,在使用get方法的时候,此时类型没有明确还是问号?我们只能明确其最大父类或者接口时,我们才能接收,但是我们只能明白<? super E>作为形参时例如List<? super E>时,只能明确Object是最大父类,其他的一概不知,所以只能Object o = list.get(0)。
B 可以使用集合的add方法添加E或者E的子类。
`原因分析`:上界通配符已经解释很清楚了,add方法添加元素时,?类型不确定就要明确该?类型的最小子类,只要比可能存在的最小子类或者子接口小的任意引用数据类型的对象,我们都可以将其添加,而下界通配符<? super E>当作形参时例如List<? super E>,此时E就是最小子类,此时add方法可以添加E或者E的父类或者接口。
2.PECS原则
PECS 是 Producer Extends Consumer Super 的缩写,是 Java 中使用泛型通配符的原则。
只读不可写时,使用List<? extends Fruit>:Producer
只写不可读时,使用List<? super Apple>:Consumer