Java泛型中的PECS原则

401 阅读2分钟

先定义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>中的一种,

如果listExtendsList<Dog>,我们无法在List<Dog>中添加Cat,但是可以从中取出Animal

如果listExtendsList<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>中的一种,

如果listSuperList<Mammal>,我们无法在List<Mammal>中添加Cat,但是可以添加Cat

如果listSuperList<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,