泛型——List 优于数组
数组与泛型有很大的不同:
1. 数组是协变的(covariant)
意思是:如果Sub是Super的子类型,则数组类型Sub[] 是数组类型Super[] 的子类型。
2. 泛型是不变的(invariant)
对于任何两种不同的类型Type1 和Type2,List<Type1> 既不是List<Type2> 的子类型也不是父类型。
现在有两段代码:
Object[] objectArray = new Long[1];
objectArray[0] = "I don't fit in";
List<Object> ol = new ArrayList<Long>(); // Incompatible types
ol.add("I don't fit in");
无论哪种方式都会报错,因为不能把一个String 类型放到一个Long 类型容器中,但是用一个数组的话,在运行时才会报错;对于列表,可以在编译时就能发现错误。所以使用列表就有优势,因为运行时报错的代价太高
3. 数组是具体化的,在运行时才知道和强化他们的类型
就比如上面的代码,将String保存到Long数组中就会得到ArrayStoreException异常
4. 泛型在编译时就强化它的类型信息,并在运行时擦除它的元素类型信息
由于上面这些区别,数组和泛型不能很好地混用,所以new List<E>[],new List<String>,new E[]这些语法都是错误的!在编译时会产生一个泛型数组创建错误。
非法的原因是它不安全,以下面这段代码为例:
List<String>[] stringLists = new List<String>[1]; // (1)
List<Integer> intList = List.of(42); // (2)
Object[] objects = stringLists; // (3)
objects[0] = intList; // (4)
String s = stringLists[0].get(0); // (5)
- 假设第1行创建一个泛型数组是合法的
- 第2行创建并初始化包含单个元素的List<Integer>
- 第3行将List<String> 数组存储到Object数组变量中,这是合法的,因为数组是协变的
- 第4行将List<Integer> 存储在Object数组的唯一元素中,这是因为泛型是通过擦除来实现的:List<String>[] 实例是List[],所以这个赋值不会产生ArrayStoreException 异常
现在问题就来了,我们将一个List<Integer> 实例存储到一个声明为List<String> 实例的数组中,为了防止这种情况出现,第一行必须报错。
E,List<E> 和List<String> 等在技术上被称为不可具体化的类型,指其运行时表示法包含的信息比它的编译时表示法包含的信息更少。唯一可具体化的参数化类型是无限制的通配符类型,如List<?>等,创建无限制通配符类型的数组是合法的,但并不常用。
当泛型数组创建错误时,最佳解决方案是使用集合类型List<E> 。例如编写一个带有集合的Chooser类和一个方法,方法返回集合中随机选择的一个元素。
public class Chooser {private final Object[] choiceArray;public Chooser(Collection choices) {choiceArray = choices.toArray();}public Object choose() {Random rnd = ThreadLocalRandom.current();return choiceArray[rnd.nextInt(choiceArray.length)];}public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("1");list.add("2");list.add("3");Chooser chooser = new Chooser(list);Object choose = chooser.choose();System.out.println(choose);}
}
如果想将choose方法的返回值从Object转换成每次调用该方法时想要的类型
public class Chooser<T> {private final T[] choiceArray;public Chooser(Collection<T> choices) {choiceArray = choices.toArray();}// choose 方法不变
}
上面的类会报错:

如果加一条强制类型转换的话:
choiceArray = (T[]) choices.toArray();
仍有报警信息:

要消除上面的警告,需要用列表代替数组:
public class Chooser<T> {private final List<T> choiceList;public Chooser(Collection<T> choices) {choiceList = new ArrayList<>(choices);}public T choose() {Random rnd = ThreadLocalRandom.current();return choiceList.get(rnd.nextInt(choiceList.size()));}
}
总结一下,数组和泛型有着截然不同的类型规则:
1. 数组是协变且可以具体化的
2. 泛型是不可变的且可以被擦除的
相关文章:
泛型——List 优于数组
数组与泛型有很大的不同: 1. 数组是协变的(covariant) 意思是:如果Sub是Super的子类型,则数组类型Sub[] 是数组类型Super[] 的子类型。 2. 泛型是不变的(invariant) 对于任何两种不同的类型Ty…...
JavaScript中对象的定义、引用和复制
JavaScript是一种广泛使用的脚本语言,其设计理念是面向对象的范式。在JavaScript中,对象就是一系列属性的集合,每个属性包含一个名称和一个值。属性的值可以是基本数据类型、对象类型或函数类型,这些类型的值相互之间有着不同的特…...
JavaScript通过函数异常处理来输入圆的半径,输出圆的面积的代码
以下为实现通过函数异常处理来输入圆的半径,输出圆的面积的代码和运行截图 目录 前言 一、通过函数异常处理来输入圆的半径,输出圆的面积 1.1 运行流程及思想 1.2 代码段 1.3 JavaScript语句代码 1.4 运行截图 前言 1.若有选择,您可以…...
Ubuntu 安装 Mysql
主要内容 本文主要是实现在虚拟机 Ubuntu 18.04 成功安装 MySQL 5.7,并实现远程访问功能,以 windows 下客户端访问虚拟机上的 mysql 数据库。 1. 切换至 root 用户 ,shell 终端指令均执行在 root 用户下 sudo su 2. 安装并设置 mysql 安…...
【五一创作】【Midjourney】Midjourney 连续性人物创作 ② ( 获取大图和 Seed 随机种子 | 通过 seed 随机种子生成类似图像 )
文章目录 一、获取大图和 Seed 随机种子二、通过 seed 种子生成类似图像 一、获取大图和 Seed 随机种子 注意 : 一定是使用 U 按钮 , 在生成的大图的基础上 , 添加 信封 表情 , 才能获取该大图的 Seed 种子编码 ; 在上一篇博客生成图像的基础上 , 点击 U3 获取第三张图的大图 ;…...
分布式事务 --- Seata事务模式、高可用
一、事务模式 1.1、XA模式 XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。…...
SQL(基础)
DDL: 数据定义语言 Definition,用来定义数据库对象(数据库、表、字段)CREATE、DROP、ALTER DML: 数据操作语言 Manipulation,用来对数据库表中的数据进行增删改 INSERT、UPDATE、DELETE 注意: DDL是改变表的结构 DML…...
「OceanBase 4.1 体验」OceanBase 4.1社区版的部署及使用体验
「OceanBase 4.1 体验」OceanBase 4.1社区版的部署及使用体验 一、前言1.1 本次实践介绍1.2 本次实践目的 二、准备环境资源2.1 部署前需准备工作2.2 本地环境规划 三、部署Docker环境3.1 安装Docker3.2 配置Docker镜像加速3.3 开启路由转发3.4 重启Docker服务 四、检查本地Doc…...
计算机操作系统实验:银行家算法模拟
目录 前言实验目的实验内容实验原理实验过程代码如下代码详解算法过程运行结果 总结 前言 本文是计算机操作系统实验的一部分,主要介绍了银行家算法的原理和实现。银行家算法是一种用于解决多个进程对多种资源的竞争和分配的算法,它可以避免死锁和资源浪…...
机器学习:多项式拟合分析中国温度变化与温室气体排放量的时序数据
文章目录 1、前言2、定义及公式3、案例代码1、数据解析2、绘制散点图3、多项式回归、拟合4、注意事项 1、前言 当分析数据时,如果我们找的不是直线或者超平面,而是一条曲线,那么就可以用多项式回归来分析和预测。 2、定义及公式 多项…...
一个 24 通道 100Msps 逻辑分析仪
这是一个创建非常便宜的逻辑分析仪的项目,但其功能可与昂贵的商业分析仪相媲美。该分析仪可以以每秒 1 亿个样本的最高速度对多达 24 个通道进行采样,并且可以通过单个通道中的极性变化或多达 16 个通道形成的模式来触发。 该项目不仅包含硬件࿰…...
使用Process Explorer和Dependency Walker排查C++程序中dll库动态加载失败问题
目录 1、exe主程序启动时的库加载流程说明 2、加载dll库两种方式 2.1、dll库的隐式引用...
网工Python:如何使用Netmiko的SCP函数进行文件传输?
在网络设备管理中,传输配置文件、镜像文件等是经常需要进行的操作。Netmiko是一个Python库,可用于与各种网络设备进行交互,提供了一些用于传输文件的函数,其中包括SCP(Secure Copy Protocol)函数。本文将介…...
题目 3166: 蓝桥杯2023年第十四届省赛真题-阶乘的和--不能完全通过,最好情况通过67.
原题链接: 题目 3166: 蓝桥杯2023年第十四届省赛真题-阶乘的和 https://www.dotcpp.com/oj/problem3166.html 致歉 害,首先深感抱歉,这道题还是没有找到很好的解决办法。目前最好情况就是67分。 这道题先这样跳过吧,当然以后还…...
ChatGPT- OpenAI 的 模型(Model) 介绍
ChatGPT的火爆程度大家都知道了,该章节我们来了解一下 ChatGPT 一个关键概念 - 模型(Model)。主要是为大家介绍一下在 OpenAI 中,究竟有哪些模型可以使用。 在后续的章节,我们会分单独的小章节逐一的为大家介绍各个不同模型的调用以及接口参…...
X 态及基于 VCS 的 X-Propagation 检测
🔥点击查看精选 IC 技能树系列文章🔥 🔥点击进入【芯片设计验证】社区,查看更多精彩内容🔥 📢 声明: 🥭 作者主页:【MangoPapa的CSDN主页】。⚠️ 本文首发于CSDN&#…...
数据库之事务隔离级别详解
事务隔离级别详解 一、事务的四大特性(ACID)1. 原子性(atomicity):2. 一致性(consistency):3. 隔离性(isolation):4. 持久性(durability): 二、事务的四种隔离级别1. 读未提交(Read uncommitted)࿱…...
守护进程、僵尸进程、孤儿进程
守护进程、僵尸进程、孤儿进程 守护进程(Daemon Process) 定义 守护进程又称Daemon进程(精灵进程),是Linux中的后台服务进程。 它的生命周期较长,通常独立于控制终端并且周期性地执行某种任务或者等待处…...
软件设计师笔记
软件设计师笔记 计算机组成与体系结构 数据的表示、计算机结构、Flynn分类法、CISC与RISC、流水线技术、存储系统、总线系统、可靠性、校验码 1. 数据的表示 (一)进制转换 R进制转十进制使用按权展开法: 十进制转R进制使用短除法 二进制…...
4_用dockerfile制作镜像
Docker 镜像原理 思考: Docker 镜像本质是什么? Docker 中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要几个个G? Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MBÿ…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
