什么是泛型擦除

简介: Java泛型在编译后会被擦除,仅保留原始类型。例如,List<String>和List<Integer>在运行时均变为List,通过反射可向本应存整数的集合添加字符串,证明泛型类型信息已被擦除,JVM无法感知其区别。

我们都知道Java的泛型是伪泛型,即编译期间所有的泛型信息都会被擦除,如我们代码定义了:List<Object>和List<String>,但是对于JVM而言,看到的只有List,由泛型附加的类型信息对于JVM而言是看不到的。代码说明如下:

1.1 原始类型擦除后相等

public class Test {
    public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<String>();
        list1.add("abc");
        ArrayList<Integer> list2 = new ArrayList<Integer>();
        list2.add(123);
        System.out.println(list1.getClass() == list2.getClass());
    }
}

在这个例子中,我们定义了两个ArrayList数组,不过一个是ArrayList<String>泛型类型的,只能存储字符串;一个是ArrayList<Integer>泛型类型的,只能存储整数,最后,我们通过list1对象和list2对象的getClass()方法获取他们的类的信息,最后发现结果为true。说明泛型类型String和Integer都被擦除掉了,只剩下原始类型

1.2 反射添加的元素被擦除

public static void main(String[] args) 
    throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(1);  //这样调用 add 方法只能存储整形,因为泛型类型的实例为 Integer
        list.getClass().getMethod("add", Object.class).invoke(list, "asd");
        for (int i = 0; i < list.size(); i++) {
            // 输出1  asd
            System.out.println(list.get(i));
        }
    }

如果直接调用add()方法,那么只能存储整数数据,不过当我们利用反射调用add()方法的时候,却可以存储字符串,这说明了Integer泛型实例在编译之后被擦除掉了,只保留了原始类型

相关文章
|
存储 弹性计算 算法
快存储数据安全
快存储数据安全
263 0
|
4月前
|
SQL 运维 容灾
别等业务中断才补坑!RTO/RPO 核心逻辑与全场景灾备架构选型全攻略
本文系统解析容灾备份核心知识:阐明其作为业务“生命线”的必要性;深度解读RTO(恢复时间目标)与RPO(恢复点目标)的定义、误区及量化方法;厘清备份(保数据)与容灾(保业务)的本质区别;详解冷备、温备、主从热备、同城双活、两地三中心六大主流架构;提供分场景选型指南与Spring Boot+MySQL实战代码,并强调演练验证与3-2-1运维法则。
929 1
|
8月前
|
存储 安全 程序员
为什么已经删除的数据还能恢复?数据恢复的原理是什么?
删除数据并非彻底清除,而是标记为可覆盖,原内容仍暂存于存储设备中。只要未被新数据覆盖,通过专业软件即可恢复。本文详解其原理并推荐实用免费工具,支持硬盘、U盘、手机等多设备文件找回。
2043 0
|
7月前
|
存储 人工智能 自然语言处理
CXG RAG 赋能增强型 AI Actions,让企业知识“活”起来
阿里云上的 Salesforce 推出CXG RAG驱动的增强型AI Actions,通过检索增强生成技术,深度整合非结构化数据,提升AI在CRM中的专业性与准确性。赋能智能问答、客服推荐等场景,助力企业构建安全、可信、高效的Agentic Enterprise。
|
7月前
|
Java
高效遍历 Map:优先使用 entrySet 或 JDK 8 的 forEach
在Java开发中,遍历Map时推荐使用`entrySet()`或JDK 8的`forEach()`,避免通过`keySet()`重复查找值。前者直接获取键值对,效率更高;后者结合Lambda,代码更简洁。根据场景选择合适方式,提升性能与可读性。
|
7月前
|
Java 数据库 开发者
Java 类加载与代码块执行顺序详解
本文详解Java中静态代码块、实例初始化块、构造器及局部代码块的执行顺序。通过示例分析,揭示类加载与对象创建时的生命周期机制,并总结“静→局→初→构”口诀,帮助开发者合理初始化资源,避免常见错误,提升代码健壮性与可读性。
|
7月前
|
存储 安全
3.OAuth2.0四种授权模式
本文详解OAuth2授权码模式流程:A服务客户端通过B服务认证服务,经用户授权获取授权码,再换取访问令牌,从而安全调用B服务资源。该模式安全性高,广泛应用于第三方登录场景。
3.OAuth2.0四种授权模式
|
7月前
|
SQL 前端开发 测试技术
如何写好一篇技术方案(精简版)
一份好的技术方案是推动项目落地、对齐认知、降低协作成本的关键。应包含变更记录、背景、功能模块、流程图、接口设计等十大结构,遵循图文结合、聚焦可执行、简洁明了的原则,800–1500字为宜,重在指导行动而非堆砌文字。
|
7月前
|
SQL 监控 安全
生产环境发布管理:从开发到上线的全链路保障
本文详解大型互联网团队的四环境发布体系(DEV→TEST→PRE→PROD),阐述如何通过标准化流程与自动化平台实现安全、高效、可追溯的生产发布,涵盖环境职责、CI/CD核心能力及风险应对策略,助力团队实现快速迭代与零重大故障。
|
7月前
|
Java
ArrayList 的扩容机制解析
ArrayList扩容机制解析:添加元素时先检查容量,不足则触发扩容。默认初始容量为10,每次扩容1.5倍,通过数组拷贝实现,耗时O(n)。频繁扩容影响性能,建议预估容量并初始化指定大小,提升效率。