基础:
extend 关键字,使用关键字extend继承父类的所有公共方法与公共字段。对于:
● 构造方法不能被继承,子类要重写
● 父类的私有属性不能被继承。
● 使用final声明的类是最终类,也不能被继承
super关键字来实现对父类成员的访问,用来引用当前对象的父类
一个是继承,一个是引用。
常见符号:
E - Element(在集合中使用,因为集合中存放的是元素)
T - Type (Java类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的java类型(无限制通配符类型)
PECS原则
假设现在有这么一个类的继承树,Fruit -> Apple -> RedApple/GreenApple
类:
Apple
public class Apple extends Fruit {
private Double price;
public Apple(Double price) {
this.price = price;
this.show();
}
public Double getPrice() {
return price;
}
@Override
public void show() {
System.out.println("I am an app");
}
}
GreenApple
public class GreenApple extends Apple {
public GreenApple(Double price) {
super(price);
}
@Override
public void show() {
System.out.println("I am a green apple");
}
}
RedApple
public class RedApple extends Apple {
public RedApple(Double price) {
super(price);
}
@Override
public void show() {
System.out.println("I am a red apple");
}
}
测试
List<? extends Fruit> 意思: List中所有元素都是Fruit的子类(包含本身), List<? super Fruit> 意思: List中所有元素都是Fruit的父类(包含本身)
public static void main(String[] args) {
// 申明父类,使用extend的时候,里面的元素都是Fruit的子类,无法识别
// List <? extends Fruit> appList2 = new ArrayList<>();
// appList2.add(new Apple(6.0));
// appList2.add(new RedApple(8.5));
List <? super Fruit> appList3 = new ArrayList<>();
appList3.add(new Apple(6.0));
appList3.add(new RedApple(7.5));
appList3.add(new GreenApple(4.0));
System.out.println(JSON.toJSONString(appList3));
Object object = appList3.get(1);
System.out.println(JSON.toJSONString(object));
}
“?”不能添加元素
/*
1. “?”不能添加元素
以“?”声明的集合,不能往此集合中添加元素,只能读,所以它只能作为生产者(亦即它只能被迭代),如下:
*/
public static void testGeneric() {
List<?> names = Lists.newArrayList("aaa", "yan");
// names.add("ccc"); // 报错无法进行添加
// 通配符声明的集合,获取的元素都是Object类型
List<Object> allNames = Lists.newArrayList("aaaa");
allNames.addAll(names);
// 只能以Object迭代元素
for (Object name : allNames) {
System.out.println(name);
}
System.out.println("==============testGeneric===============");
}
“? extends T”也不能添加元素
/*
“? extends T”也不能添加元素
以“? extends T”声明的集合,不能往此集合中添加元素,所以它也只能作为生产者
*/
public static void testGenericExtend() {
List<? extends String> names = Lists.newArrayList("bbb");
// names.add("yan"); // 报错,无法进行添加
// 声明消费者
List<String> allNames = Lists.newArrayList("bbbb");
// 消费生产者的元素
allNames.addAll(names);
allNames.forEach(System.out::println);
System.out.println("==============testGenericExtend===============");
}
“? super T”能添加元素
/*
“? super T”能添加元素
在通配符的表达式中,只有“? super T”能添加元素,所以它能作为消费者(消费其他通配符集合)。
*/
public static void testGenericSuper() {
List<? super String> allNames = Lists.newArrayList("bbb");
// 可以直接添加本类及其父元素
allNames.add("yan");
// 可以直接添加泛型元素
List<String> names = Lists.newArrayList("bbbb");
// 也可以添加通配符泛型元素
allNames.addAll(names);
List<? extends String> names1 = Lists.newArrayList("cccc");
allNames.addAll(names1);
// 只能以Object迭代元素,因为是Object类型,就难以继续其它操作
for (Object name : allNames) {
System.out.println(name);
}
System.out.println("==============testGenericSuper===============");
}
总结:
生产者使用“? extends T”通配符,消费者使用“? super T”通配符
总结PECS原则如下:
如果要从集合中读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends)
如果要从集合中写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super)
如果既要存又要取,那么就不要使用任何通配符。