记录:293
场景:Java的<? super T>和<? extends R>理解与应用。<? super T>:表示?匹配的类型都是T的父类,包括T本身。<? extends R>:表示?匹配的类型都是类型R的子类,包括R本身。
版本:
JDK 1.8
Spring Boot 2.6.3
一、基础
1.对<? super T>和<? extends R>理解
对<? super T>和<? extends R>理解,就是对泛型的理解。
1.1 概念理解
<? super T>:表示?匹配的类型都是T的父类,包括T本身。
<? extends R>:表示?匹配的类型都是类型R的子类,包括R本身。
1.2 使用List协助理解
1.2.1 List<? extends R>
List<? extends R> list:表示集合中存放的都是R的子类(包括R本身)。
针对变量List<? extends R> list。
(1)对List做添加(add(R))操作,必须使用R或者R的子类添加到list中。
(2)对List做遍历查询操作,必须使用R遍历list,取出元素.
小结:拿到一个变量使用? extends R修饰时,应该是对该变量做查询或取元素操作,不做添加操作。这种方式修饰叫做get原则。
1.2.2 List<? super T>
List<? super T> list:表示集合中存放的都是T的父类(包括T本身)。
针对变量List<? super T> list。
(1)对List做添加(add(T))操作,必须使用T或者T的子类添加到list中。
(2)对List做遍历查询操作,必须使用T父类去遍历list,取出元素。
小结:拿到一个变量使用? super T修饰时,应该是对该变量做添加操作,不做查询操作。这种方式修饰叫做put原则。
二、应用
应用实例来理解:List<? extends R>和List<? super T>。
1.应用List<? extends R>
1.1 应用说明
Obj0101是Obj01的子类。
(1)在List<? extends Obj01> list中存放的是Obj01的所有子类(包括Obj01自身)。
(2)f1_1函数的入参是List<? extends Obj01> list,在f1_1函数中,对变量list添加元素会报错,无法确定是哪个子类,因为list存放的任何Obj01子类。
(3)在f1_1函数中,可以对变量list使用Obj01类型取出元素,因为list中的元素都是Obj01的子类(包括Obj01自身)。
(4)在f1_1函数中,针对<? extends Obj01>修饰的变量List,可以读取元素不能添加元素,也被叫做Get原则。
(5)小结:在函数中使用<? extends Obj01>修饰的变量list。
添加操作:添加元素类型必须是Obj01子类或者自身。比如本例添加子类Obj0101,在f1_1函数之外操作。
获取操作:获取元素必须遍历List<Obj01>或者List<Object>,在f1_1函数中操作。
先对List<? extends Obj01> list做添加操作,再把值传递给f1_1函数。
1.2 应用实例
应用实例,验证。
/**
* 给List<? extends R>修饰的变量传值
* List<? extends R>:表示集合中存放的都是R的子类
*/
public static void f1() {
// 子类
List<Obj01> list = new ArrayList<>();
list.add(new Obj0101("张一"));
list.add(new Obj0101("王二"));
f1_1(list);
// 自身
List<Obj01> list2 = new ArrayList<>();
list2.add(new Obj01());
f1_1(list2);
}
/**
* 1.在List<? extends Obj01> list中存放的是Obj01的所有子类(包括Obj01自身)。
* 2.f1_1函数的入参是List<? extends Obj01> list,在f1_1函数中,对变量list添加元素会报错,无法确定是哪个子类,因为list存放的任何Obj01子类。
* 3.在f1_1函数中,可以对变量list使用Obj01类型取出元素,因为list中的元素都是Obj01的子类(包括Obj01自身)。
* 4.针对<? extends Obj01>修饰的变量List,可以读取元素不能添加元素,也被叫做Get原则。
* 5.小结: 在函数中使用<? extends Obj01>修饰的变量list,
* 添加操作:添加元素类型必须是Obj01子类或者自身。比如本例添加子类Obj0101。
* 获取操作:获取元素必须遍历List<Obj01>或者List<Object>。
*/
public static void f1_1(List<? extends Obj01> list) {
for (Obj01 var : list) {
var.getGirl();
}
for (Object var : list) {
Obj01 obj01 = (Obj01) var;
obj01.getGirl();
}
}
2.应用List<? super T>
2.1 应用说明
Obj0201和Obj0202是Obj02的子类。
(1)在List<? super Obj0201> list存放的都是Obj0201的父类(包括自身)
(2)在f2_1函数的入参是List<? super Obj0201> list,在在f1_2函数,对变量list添加Obj0201的子类(包括Obj0201自身)可以的。
(3)在f2_1函数中,对变量变量List<? super Obj0201> list,使用Obj0201或者Obj0201子类取出元素是不行的,会报错,无法确定具体取出的是那种类型。
(4))在f2_1函数中,针对<? super Obj0201>修饰的变量list,可以添加元素不能读取元素,也被叫做Put原则。
(5)总结:
添加操作:添加元素类型必须是Obj0201子类或者自身,在f2_1函数之中操作。
获取操作:获取元素必须遍历List<Obj02>或者List<Object>,在f2_1函数之外操作。
先定义一个满足List<? super Obj0201> list类型的变量,再把值传递给f2_1函数,在f2_1函数中做添加操作。
2.2 应用实例
应用实例,验证。
/**
* 给List<? super T>修饰的变量传值
* ListList<? super T>:表示集合中存放的都是T的父类
*/
public static void f2() {
List<Obj02> list = new ArrayList<>();
List<? super Obj0201> list2 = f2_1(list);
for (Obj02 var : list) {
var.getGirl();
}
}
/**
* (1)在List<? super Obj0201> list存放的都是Obj0201的父类(包括自身)
* (2)在f2_1函数的入参是List<? super Obj0201> list,在在f1_2函数,对变量list添加Obj0201的子类(包括Obj0201自身)可以的。
* (3)在f2_1函数中,对变量变量List<? super Obj0201> list,使用Obj0201或者Obj0201子类取出元素是不行的,会报错,无法确定具体取出的是那种类型。
* (4))在f2_1函数中,针对<? super Obj0201>修饰的变量list,可以添加元素不能读取元素,也被叫做Put原则。
* (5)总结:
* 添加操作:添加元素类型必须是Obj0201子类或者自身,在f2_1函数之中操作。
* 获取操作:获取元素必须遍历List<Obj02>或者List<Object>,在f2_1函数之外操作。
* 先定义一个满足List<? super Obj0201> list类型的变量,再把值传递给f2_1函数,在f2_1函数中做添加操作。
*/
public static List<? super Obj0201> f2_1(List<? super Obj0201> list) {
list.add(new Obj0201("刘五"));
list.add(new Obj0201("陈六"));
list.add(new Obj0202("赵七"));
list.add(new Obj0202("张八"));
return list;
}
3.应用对象
3.1 Obj01基类
public static class Obj01 {
public Obj01() {
}
public void getGirl() {
}
}
3.2 Obj0101是Obj01子类
public static class Obj0101 extends Obj01 {
private String name;
public Obj0101(String name) {
this.name = name;
}
@Override
public void getGirl() {
System.out.println(this.name + ",真漂亮.");
}
}
3.3 Obj02基类
public static class Obj02 {
private String name;
public Obj02(String name) {
this.name = name;
}
public void getGirl() {
System.out.println(this.name + ",真漂亮.");
}
}
3.4 Obj0201是Obj02子类
public static class Obj0201 extends Obj02 {
public Obj0201(String name) {
super(name);
}
}
3.5 Obj0202是Obj0201子类
public static class Obj0202 extends Obj0201 {
public Obj0202(String name) {
super(name);
}
}
以上,感谢。
2022年8月21日