PECS 是指 Producer Extends、Consumer Super,即:
那么为什么呢?首先了解两个概念:
协变(covariant)- 向上类型转换
如果 a <= b,那么 f(a) <= f(b),即如果 a 是 b 的子类,f 是类型转换函数,那么 f(a) 是 f(b) 的子类型。
比如 Manager 是 Employee 的子类,List 是范型容器,List<? extends Emloyee> 是 List<Manager> 的父类型
逆变(contravariant)- 向下类型转换
如果 a <= b,那么 f(a) >= f(b),即如果 a 是 b 的子类,f 是类型转换函数,那么 f(b) 是 f(a) 的子类型。
比如 Manager 是 Employee 的子类,List 是范型容器,List<? super Manager> 是 List<Employee> 的父类型
用一个简单的例子进行说明:
x
// Test.java
import java.util.*;
class Employee {}
class Manager extends Employee {}
public class Test
{
public static void main(String[] args) {
List<? extends Employee> list1 = new ArrayList<Manager>();
List<? super Manager> list2 = new ArrayList<Employee>();
}
}
在上面的例子中:
list1 是只读的,并且读出来的类型是 Employee 或其父类,当向其中添加元素时将报错:
x
// Test.java
import java.util.*;
class Employee {}
class Manager extends Employee {}
public class Test
{
public static void main(String[] args) {
List<Manager> managers = new ArrayList<Manager>();
for (int i = 0; i < 3; i++) {
managers.add(new Manager());
}
List<? extends Employee> list1 = managers;
list1.add(new Employee());
list1.add(new Manager());
}
}
只能从其中读取元素:
x
// Test.java
import java.util.*;
class Employee {}
class Manager extends Employee {}
public class Test
{
public static void main(String[] args) {
List<Manager> managers = new ArrayList<Manager>();
for (int i = 0; i < 3; i++) {
managers.add(new Manager());
}
List<? extends Employee> list1 = managers;
Employee employee1 = list1.get(0);
System.out.println(employee1);
}
}
list2 是只写的,并且写入的元素类型必须是 Manager 或其子类,当从其中读取元素时将报错:
x
// Test.java
import java.util.*;
class Employee {}
class Manager extends Employee {}
public class Test
{
public static void main (String[] args) {
List<Employee> employees = new ArrayList<Employee>();
for (int i = 0; i < 3; i++) {
employees.add(new Employee());
}
List<? super Manager> list2 = new ArrayList<Employee>();
Employee emloyee1 = list2.get(0);
}
}
只能向其中写入元素:
x
// Test.java
import java.util.*;
class Employee {}
class Manager extends Employee {}
class CEO extends Manager {}
public class Test
{
public static void main(String[] args) {
List<? super Manager> list2 = new ArrayList<Employee>();
// 只能写入 Manager 及其子类
list2.add(new Manager());
list2.add(new CEO());
}
}
可是为什么呢?
综上:
生产方法的参数使用 super,消费方法的参数使用 extends,比如:
xxxxxxxxxx
// Test.java
import java.util.*;
class Employee {}
class Manager extends Employee {}
public class Test {
public static void main(String[] args) {
List<Employee> employees = new ArrayList<Employee>();
Test.produce(employees);
Test.consume(employees);
}
public static void produce(List<? super Employee> employees) {
employees.add(new Employee());
employees.add(new Manager());
}
public static void consume(List<? extends Employee> employees) {
for (Employee employee: employees) {
System.out.println(employee);
}
}
}