PECS(Producer extends and Consumer super):它是从集合的角度出发来选择使用 extends 关键字还是使用 super 关键字。
如果从一个泛型集合中获取元素,那么此时这个集合认为自己是生产者,所以它的泛型类型是生产者类型,应该用 extends。如果你想在泛型集合中添加元素,此时集合认为自己是接收者,所以它的泛型类型是消费者类型,应该用 super 关键字。
假设有个参数为集合的方法,但是你想让这个集合更灵活一点,参数不局限于 Collection<Thing> 。
情形一:遍历集合中所有元素
这个列表的泛型类型就是生产者,应该使用 Collection<? extends Thing> 。
理由是一个集合 <? extends Thing> 可以保存Thing的任何子类型,因此当您执行操作时,每个元素都将表现为Thing。 (你实际上无法向 Collection<?extends Thing> 添加任何东西,因为你无法在运行时知道集合中的哪个特定子类型。)
情形二:添加元素到集合
这个列表的泛型类型就是消费者,应该使用 Collection<? super Thing> 。Collection<? super Thing> 无论实际的参数化类型是什么,它总能容纳 Thing。 在这里你不关心集合中已有的元素,它允许添加元素。
示例代码
父类:
public class Animal {class SmallDog extends Dog {}class BigDog extends Dog {}}
子类:
public class Dog extends Animal {}
测试类:
public static void producerExtends(List<? extends Animal> animals) {// 读取animalsAnimal a1 = animals.get(0);// 添加animal//animals.add(new Animal()); //编译不通过//animals.add(new Dog()); //编译不通过}public static void consumerSuper(List<? super Dog> animals) {animals.add(new Dog());//animals.add(new Animal()); // 编译不通过Object dog = animals.get(0);}public static void main(String[] args) {List<Dog> dogs = new ArrayList<>();dogs.add(new Dog());producerExtends(dogs);consumerSuper(dogs);}
