[简单粗暴]一文彻底搞懂Java泛型中的PECS原则(在坑里躺了多年终于爬出来了)

[简单粗暴]一文彻底搞懂Java泛型中的PECS原则(在坑里躺了多年终于爬出来了)

两种限定通配符

  1. 表示类型的上界,格式为:<? extends T>,即类型必须为T类型或者T子类
  2. 表示类型的下界,格式为:<? super T>,即类型必须为T类型或者T的父类

PECS原则

生产者只能用extends,消费者只能用super

上代码

public class Fruit {
}
public class Apple extends Fruit{
}
public class Banana extends Fruit{
}

List<? extends Fruit> list 的理解

正如表面意思<? extends Fruit>表示的是泛型的类型是Fruit或者Fruit的子类,也就是说我们给list赋值时泛型可以写成Fruit或者Fruit的子类,可以是 new ArrayList(),也可以是new ArrayList(),还可以是new ArrayList()

看有些地方说"<? extends Fruit>表示list中的元素可能是Fruit或者Fruit的子类",感觉这种说法很有问题,

private static List<? extends Fruit> getExtendsList() {List<? extends Fruit> list;// Explicit type argument Fruit can be replaced with <> 意思就是new ArrayList<Fruit>() 可以写成 new ArrayList<>()list = new ArrayList<Fruit>();list = new ArrayList<Apple>();list = new ArrayList<Banana>();return list;
}

list的具体定义是new ArrayList(), new ArrayList(),还是new ArrayList(),在m1中是不知道的,最大的泛型是new ArrayList(),所以取出来的一定是Fruit,最小泛型new ArrayList(),new ArrayList()…可能有很多个,具体是哪个没办法确定,所以也没办法往里面添加元素

private static void m1( List<? extends Fruit> list) {Apple apple = new Apple();// 有可能list的定义是 list = new ArrayList<Banana>(),所以往里面添加Apple就会有问题// list.add(apple);
}

List<? super Fruit> list的理解

正如表面意思,泛型的类型是Fruit或者Fruit的父类,也就是我们给list赋值时泛型可以写Fruit或者Fruit的父类,可以是new ArrayList()也可以是 new ArrayList();

如果理解成"list中的元素是Fruit或Fruit的父类,仔细品品,漏洞百出,试想如果Fruit是个顶级接口呢?那岂不是list中只能放Object了?而且还只能是Object类本身?"

private static List<? super Fruit> getSuperList() {List<? super Fruit> list;list = new ArrayList<Fruit>();list = new ArrayList<Object>();return list;
}

list的具体定义到底是new ArrayList()或者new ArrayList()在m2方法中是没法确定的,所以往list中添加元素只能按照最小泛型处理,即按照new ArrayList()处理,获取元素时按照最大的泛型处理,即new ArrayList(),所以拿到的元素都是Object(都Object了,泛型也就没意义了),所以<? super Fruit>的意义在于往集合中添加元素,也就是"消费者只能用super"

private static void m2( List<? super Fruit> list) {Apple apple = new Apple();list.add(apple);Banana banana = new Banana();list.add(banana);
}

总结

  1. List<? extends Fruit> list 限定通配符泛型(还不确定的泛型,但是有范围),一般用于只获取
  2. List<? super Fruit> list 限定通配符泛型(还不确定的泛型,但是有范围), 一般用于只添加(也可以获取,但是获取出来的是Object,没啥意义)
  3. List list 明确的泛型,可获取,也可添加,也是我们用的最多的泛型

JDK中的PECS

java.util.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");if (srcSize < COPY_THRESHOLD ||(src instanceof RandomAccess && dest instanceof RandomAccess)) {for (int i=0; i<srcSize; i++)dest.set(i, src.get(i));} else {ListIterator<? super T> di=dest.listIterator();ListIterator<? extends T> si=src.listIterator();for (int i=0; i<srcSize; i++) {di.next();di.set(si.next());}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/769697.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SqlServer服务启动报错10013

错误提示&#xff1a;MSSQLSERVER 服务启动异常不错10013 Windows不能在本地计算机启动SQLServer(MSSQLSERVER)。有关更多信 息&#xff0c;查阅系统事件日志。如果这是非Microsoft服务&#xff0c;请与服务厂商联系&#xff0c;并 参考特定服务错误代码10013。 解决 1、先禁用…

蓝桥杯 2023 省A 颜色平衡树

树上启发式合并是一个巧妙的方法。 dsu on tree&#xff0c;可以称为树上启发式合并&#xff0c;是一种巧妙的暴力。用一个全局数组存储结果&#xff0c;对于每棵子树&#xff0c;有以下操作&#xff1a; 先遍历轻儿子&#xff0c;处理完轻儿子后将数组清零&#xff08;要再…

网络七层模型之数据链路层:理解网络通信的架构(二)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Day14-集合(二)--什么是数据结构

什么是数据结构 计算机存储和组织数据的方式 数据结构概述 数据结构是计算机底层存储、组织数据的方式 是指数据相互之间是以什么方式排列在一起的 数据结构是为了更加方便管理和使用数据&#xff0c;需要结合具体的业务场景来进行选择 精心选择的数据结构可以带来更高的运…

Linux相关命令(1)

1、找出文件夹下包含 “aaa” 同时不包含 “bbb”的文件&#xff0c;然后把他们重新生成一下。要求只能用一行命令。 find ./ -type f -name "*aaa*" ! -name "*bbb*" -exec touch {} \;文件系统操作命令 df&#xff1a;列出文件系统的整体磁盘使用情况 …

2024/3/23 蓝桥杯

P1102 A-B 数对 二分 import java.util.Arrays; import java.util.Scanner;public class Main {public static void main(String[] args) {//A-BCScanner sc new Scanner(System.in);int n sc.nextInt();int C sc.nextInt();int[] res new int[n1];for(int i1;i<n;i) {…

普通用户无法连接到docker服务

环境 tt:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.3 LTS Release: 22.04 Codename: jammy问题 tt:~$ sudo apt install docker.io -ytt:~$ docker info Client:Version: 24.0.5Context: d…

小孔平板应力集中问题matlab有限元编程【源码+PPT讲义】|三节点三角形单元|平面单元|稀疏矩阵 |Comsol网格

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

样本投递技术

投递技术 APT 组织主要以邮件作为投递载体&#xff0c;邮件的标题、正文和附件都可能携带恶意代码。主要的方式是附件是漏洞文档、附件是二进制可执行程序和正文中包含指向恶意网站的超链接这三种。 APT攻击的载荷类型&#xff1a; 文档类&#xff1a;主要是office文档、pdf文…

NEFU 《JAVA语言程序设计》实验三 类的继承、接口和多态

1. (程序题)设计具有工作能力接口Workable&#xff0c;声明抽象方法updateName()&#xff0c;通过传入的字符串修改姓名&#xff1b;声明抽象方法calculateSalary()&#xff0c;返回计算的薪资 设计员工实体类Employee&#xff0c;公司下所有员工均包含&#xff0c;姓名&#x…

数组——LEETCODE的第35题(二分法与lower_bound函数)

数组——LEETCODE的第35题&#xff08;二分法与lower_bound函数&#xff09; 本文主要是根据leetcode 35题所写的关于数组的相关内容&#xff0c;主要包括&#xff1a; 数组的的特性leetcode第35题二分法的解题lower_bound函数的使用 文章目录 数组——LEETCODE的第35题&#x…

面试题(一)

目录 1.JDK、JRE、JVM之间的区别 2.hashcode()和equals()的区别 3.String、StringBuffer、StringBuilder的区别 4.泛型中extends和super的区别 5.和equals()的区别 6.重写和重载的区别 7.List和Set的区别 8.ArrayList和LinkedList区别 9.谈谈ConcurrentHashMap的原理 …

LangChain核心模块 Retrieval——文档加载器

Retrieval ​ 许多LLM申请需要用户的特定数据&#xff0c;这些数据不属于模型训练集的一部分&#xff0c;实现这一目标的主要方法是RAG(检索增强生成)&#xff0c;在这个过程中&#xff0c;将检索外部数据&#xff0c;然后在执行生成步骤时将其传递给LLM。 ​ LangChain 提供…

Unsafe的CAS操作及线程park与unpark

如下是一个参照AQS进行的一个加锁及解锁的简单实现&#xff1a; 多线程并发进行同步业务操作&#xff1b;加锁&#xff1a;尝试进行cas 0->1操作&#xff1b;如果加锁成功则进行业务处理&#xff0c;然后进行锁释放 1->0&#xff0c;然后将列头的线程进行唤醒&#xff1…

GDAL中的地理坐标系、投影坐标系及其相互转换

目录 地理坐标系 国内常用地理坐标系 投影坐标系 国内常用投影坐标系&#xff08;不推荐使用&#xff09; 坐标转换 地理坐标转为投影坐标 投影坐标转为地理坐标 地理坐标系 原理参考这篇文章&#xff1a;地理坐标系与投影坐标系区别与联系 https://yunxingluoyun.blog.…

webserver如何从零开始?

我们要做一个项目&#xff0c;过程是怎么样的呢&#xff1f;git clone ...部署&#xff0c;测试&#xff0c;然后开始写么&#xff0c;这样你大概率会“猪脑过载”&#xff0c;对一个项目的每个部分都没有清晰认识&#xff0c;能写出什么来&#xff1f;写之前当然需要测试每个功…

Linux网络协议栈从应用层到内核层③

文章目录 1、write源码剖析2、vfs层进行数据传输3、socket层进行数据传输4、tcp层进行数据传输5、ip层进行数据传输6、网络设备层进行数据传输7、网卡驱动层进行数据传输8、数据传输的整个流程 1、write源码剖析 系统调用原型 ssize_t write(int fildes, const void *buf, si…

Linux 在线yum安装: PostgreSQL 15.6数据库

Linux 在线yum安装&#xff1a; PostgreSQL 15.6数据库 1、PostgreSQL数据库简介2、在线安装PostgreSQL15.63、配置 PostgreSQL的环境变量4、使用默认用户登录PostgreSQL5、配置 PostgreSQL 允许远程登录6、修改 PostgreSQL 默认端口7、创建数据库和表、远程用户zyl8、pgAdmin远…

MATLAB环境下基于离散小波变换和主成分平均的医学图像融合方法

随着计算机技术和生物影像工程的日趋成熟&#xff0c;医学图像为医疗诊断提供的信息越来越丰富。目前&#xff0c;由于医学成像的设备种类繁多&#xff0c;导致医生获得的图像信息差异较大。如何把这些信息进行整合供医生使用成为当务之急。基于此&#xff0c;医学图像融合技术…

Rust 实战练习 - 8. 内存,ASM,外挂 【重磅】

目标&#xff1a; C写一个Demo版本的游戏由浅入深&#xff0c;了解外挂原理Linux/Android下实现内存读取ptrace实现内存修改&#xff08;依赖第三方库&#xff09; 先准备一个C写的小游戏 #include <stdio.h> #include <string.h>struct Role {float pos_x; // …