Java泛型类型擦除以及类型擦除带来的问题--什么是泛型擦除

简介: Java泛型是伪泛型,编译后类型信息被擦除,仅保留原始类型。如`ArrayList<String>`与`ArrayList<Integer>`在运行时均为`ArrayList`,通过反射可绕过泛型限制添加非指定类型元素,证明泛型仅在编译期生效,JVM无法感知其存在。

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

相关文章
|
15小时前
|
Java
ArrayList扩容机制
ArrayList 添加元素时,首先调用 `ensureCapacityInternal()` 确保容量足够。首次添加时,最小容量设为默认值10,触发扩容;后续添加若超出当前容量(初始10,每次扩容1.5倍),则调用 `grow()` 扩容。`grow()` 将容量增加50%,并通过 `Arrays.copyOf()` 创建新数组。注意:`length` 用于数组,`length()` 用于字符串,`size()` 用于集合。
|
16小时前
|
Java
JDK
JDK配置需注意使用与公司统一的版本,避免因版本不一致导致兼容性问题,确保开发环境稳定,减少不必要的错误和调试成本。
|
16小时前
|
Java Maven
Maven
当Maven依赖拉取失败时,需提前配置公司私服及阿里云镜像,并在IDEA中正确设置。若某jar包下载失败,检查本地仓库对应目录下是否有含&quot;update&quot;的文件,若有则删除该jar所在文件夹(非全部),再刷新Maven即可解决。
|
16小时前
|
Java 测试技术 Maven
Maven——构建二方包
二方包指对外提供的JAR包,如tj-api或微服务client。通过GAV(GroupId、ArtifactId、Version)提供给调用方使用。开发测试环境Version多为固定快照版(如1.0.0-SNAPSHOT),生产环境按版本递增(如1.0.1、1.1.3),重大更新时升级主版本号(如2.0.0)。
|
16小时前
|
Java 数据库连接 Nacos
Nacos
因数据库连接失败导致服务无法启动,日志显示为JDBC错误。需定位对应conf配置文件,将其中的数据库连接信息修改为公司实际配置即可解决问题。
|
16小时前
|
关系型数据库 MySQL
|
16小时前
|
开发工具 git 开发者
git常用指令
本文介绍了常用Git命令:添加文件、拉取更新、提交修改、推送代码、强制推送、重置状态、变基操作与撤销提交,帮助开发者高效管理版本控制,规范协作流程。(238字)
|
16小时前
|
开发工具 git
|
15小时前
|
开发工具 git
git解决冲突合并
git解决冲突合并
|
16小时前
|
网络安全 开发工具 数据安全/隐私保护