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) {
// 读取animals
Animal 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);
}