PECS In Java泛型类型通配符限定之<? extends T>与<? super T>
泛型类型通配符限定 🚆
- PECS | 类型通配符限定
- 如何使用“<? extends T>”和“<? super T>”通配符
- java源码示例
PECS | 类型通配符限定
PECS原则是指在使用泛型时,当我们需要传递一个泛型集合时,如何选择适当的泛型类型通配符来限制集合中元素的类型。
这个原则有两个部分:
第一部分:“Producer Extends”,表示如果一个集合中的元素将被频繁读取而不是修改,那么我们应该使用限定类型通配符“<? extends T>”。这是因为如果我们使用非限定的类型参数 T,我们只能够保证集合中的元素是 T 类型,而不能保证它们的子类类型。但如果我们使用“<? extends T>”,我们可以确保集合中的元素类型是 T 或其子类,因此我们可以安全地从集合中读取元素并使用它们。
第二部分:“Consumer Super”,表示如果一个集合中的元素将被经常插入而不是读取,那么我们应该使用“<? super T>”通配符。这是因为使用非限定类型参数 T 时,我们只能保证集合中的元素类型是 T 或其父类类型,而不能保证它们是 T 类型或其子类类型。但如果我们使用“<? super T>”,我们可以安全地将类型为 T 或其子类类型的元素插入到集合中,因为这些元素都是 T 类型或其父类类型。
因此,PECS原则帮助我们选择适当的泛型类型通配符,以确保我们在使用泛型时能够正确地读取或修改集合中的元素,从而增强代码的可读性和可维护性。
如何使用“<? extends T>”和“<? super T>”通配符
假设我们有一个 Animal 类型和它的两个子类 Dog 和 Cat:
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
现在我们有一个方法,接受一个 Animal 类型的集合,并返回其中最后一个元素。我们可以这样实现该方法:
public static <T> T getLast(List<T> list) {if (list.isEmpty()) {return null;} else {return list.get(list.size() - 1);}
}
这个方法可以接受一个 Animal 类型的集合,但我们也可以使用限定类型通配符“<? extends T>”,来表示集合中的元素类型是 T 或其子类类型。这样我们就可以调用这个方法来获取一个元素类型为 Dog 或 Cat 的集合的最后一个元素:
List<Dog> dogs = Arrays.asList(new Dog(), new Dog());
Dog lastDog = getLast(dogs);List<Cat> cats = Arrays.asList(new Cat(), new Cat());
Cat lastCat = getLast(cats);
这里使用“<? extends T>”通配符,允许我们将 List 和 List 都传递给 getLast 方法,因为它们都是 Animal 类型的子类。
另一个示例是,假设我们有一个方法,接受一个 Animal 类型的集合和一个 Animal 类型的元素,将元素插入集合的最前面:
public static void insertFirst(List<? super Animal> list, Animal animal) {list.add(0, animal);
}
这个方法使用“<? super T>”通配符,表示集合中的元素类型是 T 或其父类类型。这样我们就可以调用这个方法来将一个类型为 Dog 或 Cat 的元素插入到一个类型为 Animal 的集合中:
List<Animal> animals = new ArrayList<>();
Dog dog = new Dog();
insertFirst(animals, dog);Cat cat = new Cat();
insertFirst(animals, cat);
这里使用“<? super Animal>”通配符,允许我们将 Animal、Dog、Cat 都插入到类型为 Animal 的集合中,因为它们都是 Animal 类型或其子类类型。
java源码示例
有一些 Java 标准库中的方法使用了“<? extends T>”和“<? super T>”通配符同时出现。一个经典的例子是 Collections.copy 方法,它将一个集合的内容复制到另一个集合中:
public static <T> void copy(List<? super T> dest, List<? extends T> src) {int srcSize = src.size();if (srcSize > dest.size()) {throw new IndexOutOfBoundsException("Source does not fit in dest");}for (int i = 0; i < srcSize; i++) {dest.set(i, src.get(i));}
}
在这个方法中,我们同时使用了“<? super T>”和“<? extends T>”通配符,因为我们需要同时支持将元素类型为 T 或其子类类型的源集合复制到元素类型为 T 或其父类类型的目标集合中。
通过使用“<? extends T>”通配符来限制源集合的元素类型,我们可以确保源集合中的元素类型是 T 或其子类类型。通过使用“<? super T>”通配符来限制目标集合的元素类型,我们可以确保目标集合中的元素类型是 T 或其父类类型。这样,即使源集合的元素类型是目标集合元素类型的子类,我们也可以安全地将源集合中的元素复制到目标集合中。
以下是使用 Collections.copy 方法的示例代码:
List<Animal> animals = new ArrayList<>(Arrays.asList(new Animal(), new Animal()));
List<Dog> dogs = Arrays.asList(new Dog(), new Dog());
Collections.copy(animals, dogs);
在这个示例中,我们将一个元素类型为 Dog 的集合复制到一个元素类型为 Animal 的集合中。由于我们在 copy 方法中使用了“<? super T>”和“<? extends T>”通配符,所以我们可以正确地将元素类型为 Dog 的集合复制到元素类型为 Animal 的集合中。
相关文章:
PECS In Java泛型类型通配符限定之<? extends T>与<? super T>
泛型类型通配符限定 🚆PECS | 类型通配符限定如何使用“<? extends T>”和“<? super T>”通配符java源码示例PECS | 类型通配符限定 PECS原则是指在使用泛型时,当我们需要传递一个泛型集合时,如何选择适当的泛型类型通配符来…...
电子招投标系统源码之了解电子招标投标全流程
随着各级政府部门的大力推进,以及国内互联网的建设,电子招投标已经逐渐成为国内主流的招标投标方式,但是依然有很多人对电子招投标的流程不够了解,在具体操作上存在困难。虽然各个交易平台的招标投标在线操作会略有不同࿰…...
admin Tips
1 获取 当前浏览器 url new URL(window.location.href)...
ToBeWritten之Radare2 使用教程
也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 转移发布平台通知:将不再在CSDN博客发布新文章,敬…...
实时翻译屏幕插件
程序插件的功能是:点击按钮,将获取屏幕截图,然后翻译输出图片。(目前只支持翻译英语) 要实现这个功能,我们可以使用Python编程语言,结合一些库来完成。以下是一个简单的实现方案: …...
代码随想录算法训练营第二天| 977,209,59
977.有序数组的平方 * 数组平方后,最大值一定是在两侧 因为可以采用双指针 package algor.trainingcamp;import java.util.Arrays;/*** author lizhe* version 1.0* description: https://leetcode.cn/problems/squares-of-a-sorted-array/** 有序数组的平方* 给…...
echarts 地图板块点击着色,移除着色
//选择省份变色 showProvince(name) { this.oldName name; this.mapChart && this.mapChart.dispatchAction({ type: geoSelect, name }) }, //移除上次点击变色 hideProvince() { this.mapChart && this.mapChart.dispatchAction({ type: geoUnSelect, name:…...
Visual Studio Code (vscode)自定义用户代码段快速打出for循环等
比如fori这样的快捷键就打不出代码块了 自定义用户代码块的方法: 工具栏 > 文件 > 首选项 > 用户代码片段 然后在弹出的搜索框中填写javascript.json 有提示 不用打全就行 (会有javascript选中) 打开配置文件javascript.json 这里面显示的就是编写代码块的例子 "…...
RocketMQ客户端配置详解
文章目录 ClientConfignamesrvAddrinstanceNameclientIPclientCallbackExecutorThreadspollNameServerIntervalheartbeatBrokerIntervalpersistConsumerOffsetIntervalvipChannelEnabledDefaultMQProducerproducerGroupcreateTopicKeydefaultTopicQueueNumssendMsgTimeoutcompr…...
STM32基于STM32CubeMX DMA + EXTI读取DS1307数据
STM32基于STM32CubeMX DMA EXTI读取DS1307数据✨申明:本文章仅发表在CSDN网站,任何其他网站,未注明来源,见此内容均为盗链和爬取,请多多尊重和支持原创!🍁对于文中所提供的相关资源链接将作不定期更换。&a…...
C#中的枚举器和迭代器
目录 一、可枚举类型和枚举器 1. 枚举器 2. 可枚举类 3. 使用 IEnumerable 和 IEnumerator 案例 4. 泛型枚举接口 二、迭代器 1. 使用迭代器创建枚举器 2. 使用迭代器创建可枚举类 3. 常见的迭代器模式 4. 产生多个枚举类型 5. 将迭代器作为属性 6. 迭代器的实质 一…...
中山大学人工智能学院——考研上岸经验贴
文章目录初试个人基本情况408数学英语政治复试初试 首先是初试成绩,中山大学在2.21号就公布了成绩和排名,这点很不错,有很多学校只公布成绩而没有排名。我的初试总分386,总排名第二,各个科目还是比较平均的࿱…...
ThreeJS-圣诞节表白3D贺卡(三十)
素材分享: 链接: https://pan.baidu.com/s/1l0mZWfkiLaXJfdvZ7XoY8w 提取码: i69h 提前预知: 向下滚动鼠标滑轮切换视角 关键代码: //初始化渲染器 const render new THREE.WebGLRenderer({ //设置抗锯齿,防失真 antialis: …...
040:cesium加载World Terrain地形图
第040个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中加载世界地形图。 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共64行)相关API参考:专栏目标示例效果 配置方式 1)查看基础设置:https://xiaozh…...
逻辑运算和位移指令
逻辑运算指令 AND OR NOT XOR TEST 逻辑位移指令 SHL SHR 算术位移指令 SAL SAR 小循环位移指令 ROL ROR 大循环位移指令 RCL RCR AND 逻辑与指令 汇编格式:AND 目的操作数,源操作数 执行操作:(目的操作数)&…...
大家现在都去做Linux运维了吗?
运维自互联网出现以来,都是以基础技术部门的形式出现在各个互联网公司或者其他需要网络设备的公司里面,职位由来已久,也是多次徘徊在被淘汰的边缘。很多运维人都是靠着自己良好乐观的心态坚持到现在,接受新技术并学习新技术&#…...
Webpack的编译流程是怎么样的?webpack是如何工作的?
Webpack是一款非常流行的前端构建工具,用于将多个模块打包成一个或多个静态资源。它的工作原理是将模块的依赖关系图转化为最终的静态资源。Webpack的编译流程是一个非常复杂的过程,本文将从四个方面详细介绍Webpack的编译流程,分别是入口点分…...
【ZOJ 1151】Word Reversal 题解(字符串+模拟)
问题描述 对于每个单词列表,在不改变单词顺序的情况下,将每个单词反转输出一行。 此问题包含多个测试用例! 多重输入的第一行是整数N,然后是空行,后面跟着N个输入块。每个输入块 采用问题描述中所示的格式。输入块之间…...
Dart语言操作符?和!的用法
一.基本使用 1. ? 操作符跟在类型后面,表示当前变量可为null。 int a null; //这句代码在有空安全时,编译会提示错误如果想给一个变量赋值null要如何处理呢?只需要在类型 后面添加操作符?即可,eg: int? a null…...
聚类 kmeans | 机器学习
聚类 刘建平 1、算法原理: 是一种无监督学习算法,其主要目的是将数据点分为k个簇,距离近的样本具有更高的相似度,距离近的划分为一个簇,一共划分k个簇,**让簇内距离小,簇间距离大。**距离是样…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...
