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

简介: Java泛型在编译时会进行类型擦除,仅保留原始类型。例如`List<String>`和`List<Integer>`在运行时都变为`List`,导致`getClass()`结果相同。通过反射可绕过泛型限制添加非指定类型元素,证明泛型信息在运行期不可见,仅为编译期检查机制。

1.什么是泛型擦除
我们都知道Java的泛型是伪泛型,即编译期间所有的泛型信息都会被擦除,如我们代码定义了:List和List,但是对于JVM而言,看到的只有List,由泛型附加的类型信息对于JVM而言是看不到的。代码说明如下:
1.1 原始类型擦除后相等
public class Test {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
list1.add("abc");
    ArrayList<Integer> list2 = new ArrayList<Integer>();
    list2.add(123);

    System.out.println(list1.getClass() == list2.getClass());
}

}
在这个例子中,我们定义了两个ArrayList数组,不过一个是ArrayList泛型类型的,只能存储字符串;一个是ArrayList泛型类型的,只能存储整数,最后,我们通过list1对象和list2对象的getClass()方法获取他们的类的信息,最后发现结果为true。说明泛型类型String和Integer都被擦除掉了,只剩下原始类型。
1.2 反射添加的元素被擦除
public static void main(String[] args)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ArrayList list = new ArrayList();
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泛型实例在编译之后被擦除掉了,只保留了原始类型。

相关文章
|
3月前
|
SQL 运维 分布式计算
如何做好SQL质量监控
SLS推出用户级SQL质量监控功能,集成于CloudLens for SLS,提供健康分、服务指标、运行明细、SQL Pattern分析及优化建议五大维度,助力用户全面掌握SQL使用情况,提升日志分析效率与治理能力。
如何做好SQL质量监控
|
3月前
|
Java
常见加载顺序
该程序演示Java代码块执行顺序:静态代码块最先执行,仅一次;随后是实例初始化块,每次创建对象时执行;接着调用构造器。局部代码块位于方法内,用于限制变量作用域。运行结果依次输出:静态、初始化、构造器,重复三次。
|
3月前
|
项目管理
Controller的方法参数说明
护理项目实体类,包含项目编号、名称、单位、价格、图片、护理要求等信息,支持状态(启用/禁用)与排序管理,适用于养老护理服务系统中的项目管理。
|
3月前
|
XML NoSQL Java
5.3 技术选型
本节介绍MongoDB的Java连接驱动mongodb-driver及SpringDataMongoDB持久层框架,通过搭建文章微服务工程,配置Spring Boot整合MongoDB,实现项目初始化与启动。
5.5 文章评论实体类的编写
创建实体类Comment,位于cn.itcast.article.po包中,包含评论的ID、内容、发布时间、用户信息、点赞数、回复数、状态及关联文章ID等属性,并提供getter/setter及toString方法,用于封装评论数据。
|
3月前
|
NoSQL MongoDB Windows
2-MongoDB单机部署
本文介绍MongoDB在Windows系统的安装与启动方法,包括下载32/64位安装包、解压配置、数据目录创建,并详述命令行和配置文件两种启动方式。强调选择稳定版版本(y为偶数),设置dbPath、日志路径及端口等参数,解决YAML配置中转义字符与Tab缩进问题,确保顺利部署运行。
|
3月前
|
存储 NoSQL 关系型数据库
4-MongoDB索引知识
MongoDB索引通过B树结构提升查询效率,避免全表扫描。支持单字段和复合索引,前者适用于单一字段排序与查询,后者按字段顺序构建,优化多条件查询与排序操作,显著提升大数据量下的查询性能。
|
3月前
|
JSON NoSQL MongoDB
3.4.2 文档的基本查询
MongoDB使用`find()`查询数据,支持条件筛选与投影。`find({})`查所有文档,`_id`字段默认存在;可指定条件如`{userid:&#39;1003&#39;}`查询匹配记录,用`findOne()`返回第一条。投影参数控制字段显示,如`{userid:1,nickname:1,_id:0}`仅显指定字段,省略 `_id`。
|
3月前
|
Java 开发者
线程池
线程池通过复用预先创建的线程,避免频繁创建和销毁带来的开销,提升性能。它统一管理线程生命周期,减少资源消耗,防止线程过度切换,简化多线程编程,使开发者更专注于业务逻辑。
|
3月前
|
存储 NoSQL MongoDB
3.2 数据库操作
MongoDB中使用`use 数据库名`选择或创建数据库,若不存在则自动创建。通过`show dbs`查看所有数据库,`db`查看当前库。集合需插入文档后才真正创建。数据库名须为非空、小写、不超过64字节的UTF-8字符串,不可含特殊字符。保留库包括admin(权限管理)、local(本地数据)和config(分片信息)。