行业资讯 2025年08月6日
0 收藏 0 点赞 997 浏览 1970 个字
摘要 :

文章目录 1、什么是泛型擦除 2、举例 3、会有啥问题 3.1、强制类型转换会有编译器无法检测的问题。 3.2、引用传递问题 4、解决方案 5、要用Java泛型擦除的原因 本文……




  • 1、什么是泛型擦除
  • 2、举例
  • 3、会有啥问题
    • 3.1、强制类型转换会有编译器无法检测的问题。
    • 3.2、引用传递问题
  • 4、解决方案
  • 5、要用Java泛型擦除的原因

本文主要讲解关于Java 泛型擦除相关内容,让我们来一起学习下吧!

1、什么是泛型擦除

泛型信息只存在于代码编译阶段,在进入JVM之前,与泛型相关的信息会被擦除掉。

2、举例

  • 真相就是泛型在jvm都会被替换为Object
  • List list = new ArrayList< String>();左边编译时声明的静态类型,右边是运行时实现的实际类型
  • 那么list.add时则不会限制类型
public static void main(String[] args) {
    List list = new ArrayList();
    List listString = new ArrayList<String>();
    List listInteger = new ArrayList<Integer>();

    list.add(1);
    listString.add(123);
    listInteger.add(\"kentwang\");

    System.out.println(list.size()+\"\"+listString.size()+\"\"+listInteger.size()+\"\");
    System.out.println(list.size()+\"\"+listInteger.get(0));
}
  • 之所以get返回值时Object类型时因为在ArrayList 已经将泛型E擦除了,全都变为了Object,即使后边有类型转换,或者运行而不会报错。

Java 泛型擦除详解

3、会有啥问题

3.1、强制类型转换会有编译器无法检测的问题。

List listInteger = new ArrayList<Integer>();
listInteger.add(\"KENT\");
System.out.println(\"\"+(int)listInteger.get(0));
  • 这个不会报错,我申明是list,实现是ArrayList< Integer>,编译时静态类型是List。add可以加任何类型。运行时是ArrayList< Integer>实际类型,我强转为(Integer)应该的嘛,但是会出错

3.2、引用传递问题

  • 上面的问题中,我们已经说过了T将在后期被转义成Object,那我们对引用也进行一个转化,是否行得通呢?
//都会报错
List<String> listObject = new ArrayList<Object>();
List<Object> listObject = new ArrayList<String>();

假设说我们的第一种方案是正确的,那么其实就是将一堆Object数据存入,然后再由上面所说的强制转化一般,转化成String类型,听起来完全ok,因为在List中本来存储数据的方式就是Object。但其实是会出现ClassCastException的问题,因为Object是万物的基类,但是强转是为子类向父类准备的措施。

再来假设说我们的第二种方案是正确的,这个时候,根据上方的数据String存入,但是有什么意义存在呢?最后都还是要成Object的,你还不如就直接是Object

4、解决方案

  • 用泛型通配符
  • 强制类型转为的问题和引用传递问题,在编译期就给解决了
  • 看之前的《Java 泛型通配符详解》文章

5、要用Java泛型擦除的原因

  • java泛型是伪泛型,泛型擦除就是代码在编译阶段,与泛型相关的信息会被清除。
  • 泛型本质上是给编译器检查用的,并不改变运行时的类型。
  • java5新增泛型,如果用真泛型
    • 修改 JVM 源代码,让 JVM 能正确的的读取和校验泛型信息
    • 为了兼容老程序,需为原本不支持泛型的 API 平行添加一套泛型 API(主要是容器类型)。
    • java5之下的库A,要改代码,假设B项目升级到Java5,那么,A项目必要时要升级Java5,并且改代码。
    • 因为在 Java 中不支持高版本的 Java 编译生成的 class 文件在低版本的 JRE 上运行,如果尝试这么做,就会得到 UnsupportedClassVersionError 错误。如下图所示:
ArrayList<User> users = new ArrayList<>(); ArrayList<Dog> dogs = new ArrayList<>(); System.out.println(users.getClass() == dogs.getClass()); // 输出 true
  • 思来想去怎么让老版本不该,新版本改呢?我不增加API,在编译器检查时限制你,然后在编译器里擦除变为Object,再jvm里面新老版本就一样了。

以上就是关于Java 泛型擦除 相关的全部内容,希望对你有帮助。欢迎持续关注潘子夜个人博客(www.panziye.com),学习愉快哦!

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/9927.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

986
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

463
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

347
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

455
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

516
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

831
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号