【Java】泛型在 Java 中是怎样实现的?

news2025/5/23 1:15:35

先说结论 , Java 的泛型是伪泛型 , 在运行期间不存在泛型的概念 , 泛型在 Java 中是 编译检查 + 运行强转 实现的

泛型是指 允许在定义类 , 接口和方法时使用的类型参数 , 使得代码可以在不指定具体类型的情况下操作不同的数据类型 , 从而实现类型安全的代码复用 的语言机制 .

集合框架和内置函数式接口等内容都使用了泛型 .

通配符

<>泛型类型参数列表 , 可以包含多个参数 .

?通配符 , 可以配合 extends 和 super 关键字表示不明类型的上下限 .

<T> 通常用于泛型类源码声明 , T 作为占位符表示实例化的泛型参数 .

<?> 可以用在实例化上 , 此时泛型参数不明确 , 通常不能写入变量 .

不能 Box<?> box = new Box<?>(); , 但可以声明 Box<?> box = new Box<String>(); , 这样只能安全读取 Object 元素 , 不能写入任何非 null 元素 . new 语句右侧的 <> 叫做钻石操作符 , 钻石操作符的作用是让编译器根据左侧泛型参数推断右侧的实际参数 . 如果左侧是 <?> 参数不明 , 那么右侧则必须显式指定泛型参数 .

通配符写法作用允许读取允许写入
<?>任意类型可以读取为 Object只能写入 null
<? extends T>T 或其子类型(上界)可以读取为 T不能写入具体元素
<? super T>T 或其父类型(下界)只能读取为 Object可以写入 T 或子类型

生产消费原则 ( PECS )

Producer Extends, Consumer Super .

  • 生产者使用 <? extends T> 上界通配符 : 只能读 , 不能写 .
List<? extends Number> list = new ArrayList<Integer>();

list 是 Number 或其子类类型的集合 , 可以安全地将集合元素当作 Number 读取 , 因为确定是 Number 及其子类 .

只能确定泛型参数的上界 , 实际类型不确定 , 所以不允许写入 .

  • 消费者使用 <? super T> 下界通配符 : 只能写 , 读不明白 .
List<? super Integer> list = new ArrayList<Number>();

list 是 Integer 或其父类类型的集合 , 因为 Java 向下转型是安全的 , 所以可以将 Integer 或其子类放入集合 , 因为集合元素类型一定是 Integer 或其父类 .

因为只能确定泛型参数的下界 , 所以编译期将 ? super Integer 擦除成 Object , 且读取时只能保证元素是 Object .

类型擦除

编译器将泛型类型替换成原始类型以保证向后兼容性 ( 兼容不支持泛型的旧版本 Java ) , 向类 , 接口或方法传递的泛型类型参数 类名<类型> 只在编译期存在 , 编译后泛型信息会被擦除 , 生成的字节码文件不包含具体的泛型类型 .

类型参数被擦除为它的第一个边界类型 : 如果是 T , 则擦除为祖宗类 Object , 如果是 T extends 父类 , 则擦除为父类 . 集合中 List<T> 擦除为 List .

List<String> list = new ArrayList<>();
List.add("Hello");
String s = List.get(0);
		👇
(在字节码中类似于)
List list = new ArrayList();
list.add("Hello");
String s = (String)list.get(0);

instanceof 关键字用于判断对象是否是某个类或其子类的实例 , a instanceof b 作为语句返回布氏值 .

Tips : 基本数据类型不具备继承体系 , 也不是对象 , 不能被泛型的擦除机制处理 , 所以泛型必须使用基本数据类型的包装类 .

类型擦除会导致

  1. 运行时不知道泛型类型 .

    List<String> a = new ArrayList<>();
    List<Integer> b = new ArrayList<>();
    a.equals(b); // true
    a.getClass() == b.getClass() // true
    
  2. 泛型不能用于静态字段 . 因为不同泛型实例在运行时本质上是同一个类 , 它们会共享同一个静态字段 , 如果这个静态字段是泛型参数 T 的 , 那么就会出现实例类型冲突 ( 静态字段只有一份 , 不同实例期望的类型却不同 ) .

  3. 不能用 instanceof 关键字判别泛型类 . 因为不同的泛型类在运行时被擦除为同一个类 , 此时再使用 instanceof 关键字没有任何意义 .

编译期类型检查

仍然以集合为例 , 编译期完成的任务有 :

  1. 检测传入泛型集合的字段类型是否正确 .

    List<String> list = new ArrayList<>();
    list.add("Hello");
    list.add(123); // 编译错误, int 不是 String
    
  2. 取出泛型集合对象时是否能正确映射 .

    int get = list.get(0); // 编译错误, 不能把 String 当作 int
    

类型检查本质是继承链的转换关系 , 前面提到的向上转型机制在通配符 , 类型擦除和类型检查等特性上得到充分实现 .

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

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

相关文章

开源安全大模型Foundation-Sec-8B实操

一、兴奋时刻 此时此刻,晚上22点55分,从今天早上6点左右开始折腾,花费了接近10刀的环境使用费,1天的休息时间,总算是把Foundation-Sec-8B模型跑起来了,中间有两次胜利就在眼前,但却总在远程端口转发环节出问题,让人难受。直到晚上远程Jupyter访问成功那一刻,眉开眼笑,…

【JavaWeb】MySQL

1 引言 1.1 为什么学&#xff1f; 在学习SpringBootWeb基础知识(IOC、DI等)时&#xff0c;在web开发中&#xff0c;为了应用程序职责单一&#xff0c;方便维护&#xff0c;一般将web应用程序分为三层&#xff0c;即&#xff1a;Controller、Service、Dao 。 之前的案例中&am…

微信小游戏流量主广告自动化浏览功能案例5

功能需求&#xff1a; 支持APP单行文本框输入1个小程序链接&#xff0c;在“文件传输助手”界面发送小程序链接并进入。 主要有“文章列表首页”和“文章内容”页面。每个页面支持点击弹窗广告、槽位广告、视频广告入口、视频广告内第三方广告。 弹窗广告、槽位广告、视频广…

软件的技术架构、应用架构、业务架构、数据架构、部署架构

一、各架构定义 1. 技术架构&#xff08;Technical Architecture&#xff09; 定义&#xff1a;技术架构关注的是支撑系统运行的底层技术基础设施和软件平台&#xff0c;包括硬件、操作系统、中间件、编程语言、框架、数据库管理系统等技术组件的选择和组合方式。它描述了系统…

CSS 文字样式全解析:从基础排版到视觉层次设计

CSS 文字样式目录 一、字体家族&#xff08;font-family&#xff09; 二、字体大小&#xff08;font-size&#xff09; 三、字体粗细&#xff08;font-weight&#xff09; 四、字体样式&#xff08;font-style&#xff09; 五、文本转换&#xff08;text-transform&#xf…

【高德开放平台-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

RabbitMQ的简介

三个概念 生产者&#xff1a;生产消息的服务消息代理&#xff1a;消息中间件&#xff0c;如RabbitMQ消费者&#xff1a;获取使用消息的服务 消息队列到达消费者的两种形式 队列&#xff08;queue&#xff09;:点对点消息通信&#xff08;point-to-point&#xff09; 消息进入队…

使用Gemini, LangChain, Gradio打造一个书籍推荐系统 (第一部分)

第一部分&#xff1a;数据处理 import kagglehub# Download latest version path kagglehub.dataset_download("dylanjcastillo/7k-books-with-metadata")print("Path to dataset files:", path)自动下载该数据集的 最新版本 并返回本地保存的路径 impo…

大语言模型 16 - Manus 超强智能体 Prompt分析 原理分析 包含工具列表分析

写在前面 Manus 是由中国初创公司 Monica.im 于 2025 年 3 月推出的全球首款通用型 AI 智能体&#xff08;AI Agent&#xff09;&#xff0c;旨在实现“知行合一”&#xff0c;即不仅具备强大的语言理解和推理能力&#xff0c;还能自主执行复杂任务&#xff0c;直接交付完整成…

以太联Intellinet带您深度解析PoE交换机的上行链路端口(Uplink Ports)

在当今网络技术日新月异的时代&#xff0c;以太网供电(PoE)交换机已然成为现代网络连接解决方案中不可或缺的“利器”。它不仅能够出色地完成数据传输任务&#xff0c;还能为所连接的设备提供电力支持&#xff0c;彻底摆脱了单独电源适配器的束缚&#xff0c;让网络部署更加简洁…

分类算法 Kmeans、KNN、Meanshift 实战

任务 1、采用 Kmeans 算法实现 2D 数据自动聚类&#xff0c;预测 V180,V260 数据类别&#xff1b; 2、计算预测准确率&#xff0c;完成结果矫正 3、采用 KNN、Meanshift 算法&#xff0c;重复步骤 1-2 代码工具&#xff1a;jupyter notebook 视频资料 无监督学习&#xff…

网络安全之身份验证绕过漏洞

漏洞简介 CrushFTP 是一款由 CrushFTP LLC 开发的强大文件传输服务器软件&#xff0c;支持FTP、SFTP、HTTP、WebDAV等多种协议&#xff0c;为企业和个人用户提供安全文件传输服务。近期&#xff0c;一个被编号为CVE-2025-2825的严重安全漏洞被发现&#xff0c;该漏洞影响版本1…

MySQL 主从复制搭建全流程:基于 Docker 与 Harbor 仓库

一、引言 在数据库管理中&#xff0c;MySQL 主从复制是一种非常重要的技术&#xff0c;它可以实现数据的备份、读写分离&#xff0c;减轻主数据库的压力。本文将详细介绍如何使用 Docker 和 Harbor 仓库来搭建 MySQL 主从复制环境&#xff0c;适合刚接触数据库和 Docker 的新手…

Django框架的前端部分使用Ajax请求一

Ajax请求 目录 1.ajax请求使用 2.增加任务列表功能(只有查看和新增) 3.代码展示集合 这篇文章, 要开始讲关于ajax请求的内容了。这个和以前文章中写道的Vue框架里面的axios请求, 很相似。后端代码, 会有一些细节点, 跟前几节文章写的有些区别。 一、ajax请求使用 我们先…

cmd如何从C盘默认路径切换到D盘某指定目录

以从C盘cmd打开后的默认目录切换到目录"D:\Program Files\MySQL\MySQL Server 8.0\bin\mysqld"为例 打开cmd 首先点击开始键&#xff0c;搜索cms&#xff0c;右键以管理员身份运行打开管理员端的命令行提示符 1、首先要先切换到D盘 直接输入D:然后回车就可以&…

每日Prompt:实物与手绘涂鸦创意广告

提示词 一则简约且富有创意的广告&#xff0c;设置在纯白背景上。 一个真实的 [真实物体] 与手绘黑色墨水涂鸦相结合&#xff0c;线条松散而俏皮。涂鸦描绘了&#xff1a;[涂鸦概念及交互&#xff1a;以巧妙、富有想象力的方式与物体互动]。在顶部或中部加入粗体黑色 [广告文案…

学习笔记:黑马程序员JavaWeb开发教程(2025.4.8)

12.11 登录校验-Filter-详解&#xff08;过滤器链&#xff09; 过滤器链及其执行顺序&#xff0c;一个Filter一个过滤器链&#xff0c;类名排名越靠前&#xff08;按照ABC这样的顺序&#xff09;&#xff0c;就先执行谁 12.12 登录校验-Filter-登录校验过滤器 获取请求参数&…

Ubuntu部署私有Gitlab

这个东西安装其实挺简单的&#xff0c;但是因为我这边迁移了数据目录和使用自己安装的 nginx 代理还是踩了几个坑&#xff0c;所以大家可以注意下 先看下安装 # 先安装必要组件 sudo apt update sudo apt install -y curl openssh-server ca-certificates tzdata perl# 添加gi…

genicamtl_lmi_gocator_objectmodel3d

目录 一、在halcon中找不到genicamtl_lmi_gocator_objectmodel3d例程二、在halcon中运行genicamtl_lmi_gocator_objectmodel3d,该如何配置三、代码分段详解(一)传感器连接四、代码分段详解(二)采集图像并显示五、代码分段详解(三)坐标变换六、常见问题一、在halcon中找不…

[LevelDB]LevelDB版本管理的黑魔法-为什么能在不锁表的情况下管理数据?

文章摘要 LevelDB的日志管理系统是怎么通过双链表来进行数据管理为什么LevelDB能够在不锁表的情况下进行日志新增 适用人群: 对版本管理机制有开发诉求&#xff0c;并且希望参考LevelDB的版本开发机制。数据库相关从业者的专业人士。计算机狂热爱好者&#xff0c;对计算机的…