Java泛型类型擦除以及类型擦除带来的问题

简介: Java泛型在编译后会进行类型擦除,仅保留原始类型。例如,List<String>和List<Integer>在运行时均变为List,泛型信息不复存在。通过反射可向声明为Integer的列表添加字符串,证明泛型类型被擦除,JVM无法感知其原始泛型约束。

1.什么是泛型擦除

我们都知道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泛型实例在编译之后被擦除掉了,只保留了原始类型。

相关文章
|
XML JSON API
高效使用 Postman:如何正确传递 Query、Path 和 Body 参数
Postman 作为一个功能强大的工具,极大地简化了 API 测试和调试的过程,提供了发送请求和检查响应的直接方法。本文将着重介绍如何在 Postman 中高效地处理请求参数,以提高 API 测试和开发的便利性。
|
5月前
|
存储 运维 算法
【分布式】分布式系统核心知识体系:CAP定理、BASE理论与核心挑战
本文构建“理论边界→工程落地→现实挑战”闭环知识体系,深度解析CAP定理(分布式不可突破的不可能三角)、BASE理论(AP场景下的柔性实践)及八大类核心工程挑战,厘清误区,建立系统化认知框架。
|
11月前
|
人工智能 监控 安全
拔俗AI集成化管控平台:让智能应用“管得住、跑得稳”的技术底座
AI集成化管控平台是支撑AI规模化落地的“幕后基建”,涵盖资源调度、服务编排与全链路治理三大核心层,实现模型统一管理、服务标准化输出与系统稳定可控,助力企业构建高效、安全、可追溯的AI应用体系。
542 1
|
9月前
|
消息中间件 Cloud Native Java
SpringCloud概述
Spring Cloud是Spring推出的微服务一站式解决方案,弥补了分散技术栈的整合难题。它具备约定大于配置、组件丰富、开箱即用等特点,完美支持云原生架构。版本以伦敦地铁站命名,如Hoxton.SR12,避免与子项目版本冲突,便于统一管理。
SpringCloud概述
|
9月前
|
存储 关系型数据库 MySQL
为什么MySQL索引结构是B+tree ?
MySQL采用B+树作为索引结构,因其非叶子节点仅存键值与指针,可存储更多键,降低树高,提升查询效率。数据集中于叶子节点并形成双向链表,支持高效稳定的范围查询。通常树高为2-3层,即可容纳上千万数据,显著优于二叉树或B树。
|
9月前
|
安全 Java 索引
说说 java 中常见的集合类
本文介绍了Java集合框架的核心接口(Collection、List、Set、Map)及其常见实现类。图示展示了类间关系,重点解析ArrayList、LinkedList、HashSet、HashMap等实现原理与性能特点,并指出线程安全及进阶特性,助你掌握集合体系关键知识点。
|
9月前
|
缓存 安全
String,StringBuilder 和 StringBuffer 的区别
String不可变,StringBuilder与StringBuffer可变;后者线程不安全,StringBuffer线程安全。大量拼接时优先选用后两者,多线程用StringBuffer,单线程用StringBuilder。String因final设计保证不可变,利于安全与缓存。
HTTP协议中常见的状态码 ?
HTTP状态码分为1xx、2xx、3xx、4xx、5xx五类。常见状态码包括:101(切换协议,如WebSocket)、200(请求成功)、302(重定向)、401(未认证)、404(资源未找到)、500(服务器内部错误),广泛应用于Web开发中。
|
9月前
|
安全
HTTP协议中请求方式GET 与 POST 什么区别 ?
简介:项目开发中常见GET与POST请求方式,主要区别在于参数传递位置、大小限制及安全性。GET用于获取数据,参数在URL中;POST用于提交数据,参数在请求体中,更安全。现代项目多采用RESTful风格,通过URL定位资源,不同请求方式(GET/POST/PUT/DELETE)对应不同操作,提升接口规范性与可读性。(238字)
|
9月前
|
算法 数据安全/隐私保护
比较一下 RSA、ECDSA 和 SM2
RSA、SM2均为非对称加密算法。SM2基于椭圆曲线,密钥长度256位,安全性高且运算更快;RSA依赖大数分解,密钥通常1024-4096位。SM2为国密算法,受国内政策支持。ECDSA与SM2原理相似。

热门文章

最新文章