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

相关文章
|
17小时前
|
SQL 运维 分布式计算
如何做好SQL质量监控
SLS推出用户级SQL质量监控功能,集成于CloudLens for SLS,提供健康分、服务指标、运行明细、SQL Pattern分析及优化建议五大维度,助力用户全面掌握SQL使用情况,提升日志分析效率与治理能力。
如何做好SQL质量监控
|
17小时前
3.5.2 分页列表查询
使用limit()限制查询返回的记录数,skip()跳过指定数量数据,实现分页。如每页2条:第一页skip(0).limit(2),第二页skip(2).limit(2),以此类推,默认limit为20,skip为0。
|
17小时前
3.5 文档的分页查询
统计查询使用count()方法,可统计集合中符合条件的记录数量。语法为db.collection.count(query, options)。如统计comment集合全部记录:db.comment.count();按条件统计userid为1003的记录数:db.comment.count({userid:&quot;1003&quot;})。默认返回所有匹配文档的数量。
|
18小时前
3.3.3 集合的删除
集合删除语法为 `db.collection.drop()` 或 `db.集合.drop()`,成功返回 true,失败返回 false。例如:`db.mycollection.drop()` 可删除 mycollection 集合。
|
17小时前
|
存储 NoSQL MongoDB
3.2 数据库操作
MongoDB中使用`use 数据库名`选择或创建数据库,若不存在则自动创建。通过`show dbs`查看所有数据库,`db`查看当前库。集合需插入文档后才真正创建。数据库名须为非空、小写、不超过64字节的UTF-8字符串,不可含特殊字符。保留库包括admin(权限管理)、local(本地数据)和config(分片信息)。
|
18小时前
|
存储 安全 Java
3.泛型擦除引起的问题及解决方法
Java泛型在编译时进行类型检查并擦除类型信息,类型检查针对引用而非对象本身。擦除后泛型转为原始类型,通过自动强转实现安全取值。泛型不支持基本类型,静态成员不能使用类的泛型参数,但泛型方法可独立定义类型参数。instanceof不可用于泛型类型判断。
|
17小时前
|
存储 NoSQL Linux
2.4 Linux系统中的安装启动和连接
本文介绍在Linux系统部署单机MongoDB用于生产环境的完整步骤,包括下载、解压、目录配置、日志与数据路径设置、配置文件编写及服务启停方法。操作类似Windows,通过配置`mongod.conf`实现后台运行,支持命令行与图形工具连接,并提供防火墙处理与安全关闭服务方案,确保稳定运行。
|
17小时前
|
存储 NoSQL MongoDB
4.2.3 其他索引
MongoDB提供地理空间索引支持平面与球面查询,文本索引实现高效字符串搜索并提取词干,哈希索引则用于散列分片,仅支持等值匹配,提升数据分布随机性。
|
17小时前
|
存储 NoSQL 关系型数据库
4-MongoDB索引知识
MongoDB索引通过B树结构提升查询效率,避免全表扫描。支持单字段和复合索引,前者适用于单一字段排序与查询,后者按字段顺序构建,优化多条件查询与排序操作,显著提升大数据量下的查询性能。