先定义Animal,Mammal,Cat,Dog类
class Animal{
}
class Mammal{
}
class Cat extends Mammal{
}
class Dog extends Mammal{
}
他们的继承关系如下:

创建如下对象:
List<? extends Animal> listExtends = new ArrayList<>();
List<? super Cat> listSuper = new ArrayList<>();
List<Animal> animals = new ArrayList<>();
List<Mammal> mammals = new ArrayList<>();
List<Cat> cats = new ArrayList<>();
List<Dog> dogs= new ArrayList<>();
这里<? extends Animal>表示listExtends的类型参数是Animal或者Animal的子类,而不是存储的元素类型.换句话说List<? extends Animal>可能是List<Animal>,List<Mammal>, List<Cat> ,List<Dog>.
listExtends = animals;// 编译通过
listExtends = mammals;// 编译通过
listExtends = cats;// 编译通过
listExtends = dogs;// 编译通过
因为List<? extends Animal>可能是List<Animal>,List<Mammal>, List<Cat>,List<Dog>中的一种,
如果listExtends是List<Dog>,我们无法在List<Dog>中添加Cat,但是可以从中取出Animal
如果listExtends是List<Mammal>,我们无法在List<Mammal>中添加Animal,但是可以从中取出Animal
dogs.add(new Cat()); // error 编译不通过
mammals.add(new Animal()); // error 编译不通过
Animal element = dogs.get(0); // 编译通过
Animal element = cats.get(0); // 编译通过
Animal element = mammals.get(0); // 编译通过
Animal element = animals.get(0); // 编译通过
Animal element = listExtends.get(0); // 编译通过
所以我们可以从listExtends取出Animal元素,但是不能往listExtends添加元素.
我们再来看看super限定符,对于List<? super Cat>,它表示listSuper的类型参数是Cat或者是Cat的父类,并不是存储的元素类型.换句话说List<? super Cat>可能是List<Animal>,List<Mammal>, List<Cat>.
listSuper = animals;// 编译通过
listSuper = mammals;// 编译通过
listSuper = cats;// 编译通过
因为List<? super Cat>可能是List<Animal>,List<Mammal>, List<Cat>中的一种,
如果listSuper是List<Mammal>,我们无法在List<Mammal>中添加Cat,但是可以添加Cat
如果listSuper是List<Animal>,我们无法在List<Animal>中取出Cat,Mammal,但是可以添加Cat
Cat cat = mammals.get(0); // error 编译不通过
Cat cat = animals.get(0); // error 编译不通过
Mammal mammal = animals.get(0); // error 编译不通过
animals.add(new Cat()); // 编译通过
mammals.add(new Cat()); // 编译通过
cats.add(new Cat()); // 编译通过
所以我们可以往listSuper添加Cat类似的元素,但是不能从listSuper取出元素.
总结
如果将只能读取的称作生产者,只能写入的称作消费者.
当我们使用extends限定符时,我们只能读取,当我们使用super限定符时,我们只能写入.
这就是Java泛型中的PECS原则– Producer Extends Consumer Super,