Java泛型的<? super T>,<? extend T>的区别
? extends T
? extends T 描述了通配符上界, 即具体的泛型参数需要满足条件: 泛型参数必须是 T 类型或它的子类, 例如:
List<? extends Number> numberArray = new ArrayList<Number>(); // Number 是 Number 类型的
List<? extends Number> numberArray = new ArrayList<Integer>(); // Integer 是 Number 的子类
List<? extends Number> numberArray = new ArrayList<Double>(); // Double 是 Number 的子类
上面三个操作都是合法的, 因为 ? extends Number 规定了泛型通配符的上界, 即我们实际上的泛型必须要是 Number 类型或者是它的子类, 而 Number, Integer, Double 显然都是 Number 的子类(类型相同的也可以, 即这里我们可以认为 Number 是 Number 的子类).
子类型判断
假设有类型 G, 以及 SuperClass 和 SubClass 两个类, 并且 SuperClass 是 SubClass 的父类, 那么:
-
G<? extends SubClass> 是 G<? extends SuperClass> 的子类型. 如 List<? extends Integer> 是 List<? extends Number> 的子类型
-
G 是 G<? extends SuperClass> 的子类型, 例如 List 是 List<? extends Integer> 的子类型.
-
G<?> 和 G<? extends Object> 等同.
可以想象 G<? extends T> 为一个左闭右开的区间(T 在最左边), G<? extends Object> 是最大的区间, 当区间 G<? extends SuperClass> 包含 区间 G<? extends SubClass>时, 那么较大的区间就是父类.
关于读取
根据上面的例子, 对于 List<? extends Number> numberArray 对象:
-
我们能够从 numberArray 中读取到 Number 对象, 因为 numberArray 中包含的元素是 Number 类型或 Number 的子类型.
-
我们不能从 numberArray 中读取到 Integer 类型, 因为 numberArray 中可能保存的是 Double 类型.
-
同理, 我们也不能从 numberArray 中读取到 Double 类型.
关于写入
根据上面的例子, 对于 List<? extends Number> numberArray 对象:
-
我们不能添加 Number 到 numberArray 中, 因为 numberArray 有可能是List 类型
-
我们不能添加 Integer 到 numberArray 中, 因为 numberArray 有可能是 List 类型
-
我们不能添加 Double 到 numberArray 中, 因为 numberArray 有可能是 List 类型
即, 我们不能添加任何对象到 List<? extends T> 中, 因为我们不能确定一个 List<? extends T> 对象实际的类型是什么, 因此就不能确定插入的元素的类型是否和这个 List 匹配. List<? extends T> 唯一能保证的是我们从这个 list 中读取的元素一定是一个 T 类型的.
? super T
? super T 描述了通配符下界, 即具体的泛型参数需要满足条件: 泛型参数必须是 T 类型或它的父类, 例如:
// 在这里, Integer 可以认为是 Integer 的 "父类"
List<? super Integer> array = new ArrayList<Integer>();
// Number 是 Integer 的 父类
List<? super Integer> array = new ArrayList<Number>();
// Object 是 Integer 的 父类
List<? super Integer> array = new ArrayList<Object>();
关于读取
对于上面的例子中的 List<? super Integer> array 对象:
- 我们不能保证可以从 array 对象中读取到 Integer 类型的数据, 因为 array 可能是 - List< Number > 类型的.
- 我们不能保证可以从 array 对象中读取到 Number 类型的数据, 因为 array 可能是 List< Object > 类型的.
- 唯一能够保证的是, 我们可以从 array 中获取到一个 Object 对象的实例.
关于写
对于上面的例子中的 List<? super Integer> array 对象:
-
我们可以添加 Integer 对象到 array 中, 也可以添加 Integer 的子类对象到 array 中.
-
我们不能添加 Double/Number/Object 等不是 Integer 的子类的对象到 array 中.
易混淆点
有一点需要注意的是, List<? super T> 和 List<? extends T> 中, 我们所说的 XX 是 T 的父类(a superclass of T) 或 XX 是 T 的子类(a subclass of T) 其实是针对于泛型参数而言的. 例如考虑如下例子:
List<? super Integer> l1 = ...
List<? extends Integer> l2 = ...
那么这里 ? super Integer 和 ? extends Integer 的限制是对谁的呢? 是表示我们可以插入任意的对象 X 到 l1 中, 只要 X 是 Integer 的父类? 是表示我们可以插入任意的对象 Y 到 l2 中, 只要 Y 是 Integer 的子类?
其实不是的, 我们必须要抛弃上面的概念, ? super Integer 和 ? extends Integer 限制的其实是 泛型参数, 即 List<? super Integer> l1 表示 l1 的泛型参数 T 必须要满足 T 是 Integer 的父类, 因此诸如 List< Object >, List< Number >的对象就可以赋值到 l1 中. 正因为我们知道了 l1 中的泛型参数的边界信息, 因此我们就可以向 l1 中添加 Integer 对象了, 推理过程如下:
令 T 是 l1 的泛型参数, 即:l1 = List<T> = List<? super Integer>
因此有 T 是 Integer 或 Integer 的父类.
如果 T 是 Integer, 则 l1 = List<Integer>, 显然我们可以添加任意的 Integer 对象或 Integer 的子类对象到 l1 中.
如果 T 是 Integer 的父类, 那么同理, 对于 Integer 或 Integer 的子类的对象, 我们也可以添加到 l1 中.
按同样的分析方式, List<? extends Integer> l2 表示的是 l2 的泛型参数是 Integer 的子类型. 而如果我们要给一个 List 插入一个元素的话, 我们需要保证此元素是 T 或是 T 的子类, 而这里 List<? extends Integer> l2, l2 的泛型参数是什么类型我们都不知道, 进而就不能确定 l2 的泛型参数的子类是哪些, 因此我们就不能向 l2 中添加任何的元素了.
来一个对比:
-
对于 List<? super Integer> l1:
-
正确的理解: ? super Integer 限定的是泛型参数. 令 l1 的泛型参数是 T, 则 T 是 Integer 或 Integer 的父类, 因此 Integer 或 Integer 的子类的对象就可以添加到 l1 中.
-
错误的理解: ? super Integer限定的是插入的元素的类型, 因此只要是 Integer 或 Integer 的父类的对象都可以插入 l1 中
-
-
对于 List<? extends Integer> l2:
-
正确的理解: ? extends Integer 限定的是泛型参数. 令 l2 的泛型参数是 T, 则 T 是 Integer 或 Integer 的子类, 进而我们就不能找到一个类 X, 使得 X 是泛型参数 T 的子类, 因此我们就不可以向 l2 中添加元素. 不过由于我们知道了泛型参数 T 是 Integer 或 Integer 的子类这一点, 因此我们就可以从 l2 中读取到元素(取到的元素类型是 Integer 或 Integer 的子类), 并可以存放到 Integer 中.
-
错误的理解: ? extends Integer 限定的是插入元素的类型, 因此只要是 Integer 或 Integer 的子类的对象都可以插入 l2 中
-
使用场景
PECS 原则: Producer Extends, Consumer Super
-
Producer extends: 如果我们需要一个 List 提供类型为 T 的数据(即希望从 List 中读取 T 类型的数据), 那么我们需要使用 ? extends T, 例如 List<? extends Integer>. 但是我们不能向这个 List 添加数据.
-
Consumer Super: 如果我们需要一个 List 来消费 T 类型的数据(即希望将 T 类型的数据写入 List 中), 那么我们需要使用 ? super T, 例如 List<? super Integer>. 但是这个 List 不能保证从它读取的数据的类型.
-
如果我们既希望读取, 也希望写入, 那么我们就必须明确地声明泛型参数的类型, 例如 List< Integer >.
例子:
public class Collections { public static <T> void copy(List<? super T> dest, List<? extends T> src) {for (int i=0; i<src.size(); i++) dest.set(i,src.get(i)); }
}
上面的例子是一个拷贝数据的代码, src 是 List<? extends T> 类型的, 因此它可以读取出 T 类型的数据(读取的数据类型是 T 或是 T 的子类, 但是我们不能确切的知道它是什么类型, 唯一能确定的是读取的类型 is instance of T), , dest 是 List<? super T> 类型的, 因此它可以写入 T 类型或其父类的数据…
相关文章:
Java泛型的<? super T>,<? extend T>的区别
? extends T ? extends T 描述了通配符上界, 即具体的泛型参数需要满足条件: 泛型参数必须是 T 类型或它的子类, 例如: List<? extends Number> numberArray new ArrayList<Number>(); // Number 是 Number 类型的 List<? extends Number>…...
如何做出好看的Excel可视化图表?
可视化死磕excel是不行的,作为数据分析行业的偷懒大户,分享一些我在可视化工具上的使用心得,总结了三大类:快速出图类、专业图表类、高端大屏类。个人经验,大家按需采纳: 一、快速出图类 如果你只是因为偶…...
智能吸吹一体式方案设计特点
一、家用吸吹一体吸尘器方案研发设计要素: 1.小巧的机身设计,一手掌握,无论是床底、沙发下还是家具缝隙之中都能够使用。 2.无线,插电两用,在家方便可插电使用。内置可充电锂电池,充满电也可无线使用。 3.采…...
CSDN 编辑器 Marddown 语法备忘
原文链接:https://blog.csdn.net/blogdevteam/article/details/103478461 本文对其二次加工,增加渲染样式、补充例程、添加未收录的常用语法。 CSDN Markdown 编辑器遵循 CommonMark spec 语法规范。 快捷键 撤销:Ctrl/Command Z 重做&…...
回归预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优化双向长短期记忆网络多输入单输出回归预测
回归预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优化双向长短期记忆网络多输入单输出回归预测 目录回归预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优化双向长短期记忆网络多输入单输出回归预测预测效果基本介绍程序设计参考资料预测效果 基本介绍 Matlab实现NGO-BiLSTM北方苍鹰算法…...
Linux——操作系统安装
个人简介:云计算网络运维专业人员,了解运维知识,掌握TCP/IP协议,每天分享网络运维知识与技能。个人爱好: 编程,打篮球,计算机知识个人名言:海不辞水,故能成其大;山不辞石…...
AFLNET lightftp项目报错解决方法
在学习AFLNET的时候,本人尝试对示例项目中的lightftp进行fuzz,而后出现如下报错: AFLNet - the states hashtable should always contain an entry of the initial state 在github项目issue里看到了有人的问题和我一摸一样,Stack Overflow里…...
av 146 003
121. 团队章程的目标是什么? A. 使团队正规化,以便能够清楚地了解资源分配和参与情况 B. 创造一个团队可以自我管理和自我指导的环境 C. 创造一个环境,使团队成员能够尽其所能地工作 D. 创造一种团队归属感,促进包容性和协作性的行为 12…...
干了1年“点点点”,自己辞职了,下一步是继续干测试还是转开发?
最后后台有个粉丝向我吐槽,不知道怎么选择了....下面就他的情况说说怎么选择? 目前已经提桶跑路,在大工厂里混了半年初级低级功能测试经验,并没有什么用。测试培训班来的。从破山村贫困户贫困专项出去的,学校上海的。…...
国产技术迎来突破,14nm芯片横空出世,低代码也有好消息
芯片,被称为工业时代的“粮食”,小到手机手环,大到飞机轮船,几乎各个行业都不离开芯片的支持,其重要性不言而喻。而我国在这一领域一直较为薄弱。 一、“芯片之路坎坷” 由于国内半导体芯片市场底子薄弱、没有主动权…...
使用clickhouse-backup工具备份clickhouse数据库
工具官网:https://github.com/AlexAkulov/clickhouse-backup/dockerhub工具官网:https://hub.docker.com/r/alexakulov/clickhouse-backup注意:这个工具只支持MergeTree 系列表引擎一、clickhouse在容器外的备份和恢复若clickhouse装在容器外…...
python cartopy绘制扇形区域图/cartopy绘制北极部分区域
问题 当绘图时,往往并不需要绘制整块区域,而是想聚焦于局部地区,此时我们需要绘制扇形图。 在cartopy中,只提供普通正方形的框架,如果我们需要其他,边界,需要自己去绘制,最常见的是…...
如何设置股票接口版交易软件的指标涨跌家数?
如何设置股票接口版交易软件指标涨跌家数?今天小编就以通达信为例给大家介绍一下,很多人其实不知道通达信里面有个很厉害的股票情绪的指标,叫做通达信涨跌家数,打开在通达信软件k线界面,然后输入880005就可以找到了。下…...
C++之lambda函数(匿名函数)
lambda函数简介lambda函数是C11标准新增的语法,也称为lambda表达式或匿名函数。lambda函数的特点是:距离近、简洁、高效和功能强大。优点声明式编程风格:就地匿名定义目标函数或函数对象,有更好的可读性和可维护性。简洁ÿ…...
WGCNA | 值得你深入学习的生信分析方法!~(网状分析-第四步-模块的功能注释)
1写在前面 前面我们用WGCNA分析得到多个模块,其中有一些模块和我们感兴趣的表型或者临床特征是相关的。🥳 接着就是要做模块的富集分析了,帮助我们了解这些模块的基因都有哪些已知的功能,涉及到哪些通路,在哪些疾病中最…...
如何看待年轻人躺平式生活观?
theme: smartblue 如何看待年轻人躺平式生活观? 躺平:网络流行词。指无论对方做出什么反应,你内心都毫无波澜,对此不会有任何反应或者反抗,表示顺从心理。另外在部分语境中表示为:瘫倒在地,…...
JS 设计模式 - 怎么让你的代码提示一个档次
设计模式是我们在解决一些问题的时候 ,针对特定的问题给出的简介并且优化的处理方案 这篇文章说提及到的 JavaScript 设计模式将围绕着封装方法类来展开叙述 构造器模式 构造器模式本质就是我们平常在编码中常用的封装方法,重复利用构造函数 // 这是…...
遮挡贴图(Occlusion Map)和微表面贴图(Microsurface Map)
遮挡贴图(Occlusion Map) 在3D图形学中,遮挡(Occlusion)是指光被物体挡住。即便是在PBR中,环境光在某些应该被遮挡的地方,也会以古怪的方式被反射。遮挡贴图(Occlusion Mapÿ…...
【Vue】基本交互指令
Vue el挂载点 <div id"app">{{message}} </div> <script>var app new Vue({el:"#app",data:{message:"hello"}}) </script>Vue实例的作用范围:管理el选项命中的元素及其内部的后代元素使用其他的选择器&a…...
MySQL 中的 distinct 和 group by 哪个效率更高?
结论先说大致的结论(完整结论在文末):在语义相同,有索引的情况下group by和distinct都能使用索引,效率相同。在语义相同,无索引的情况下:distinct效率高于group by。原因是distinct 和 group by…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
