当前位置: 首页 > news >正文

【Java基础面试题034】Java泛型擦除是什么?

回答重点

泛型擦除指的是Java编译器在编译时将所有泛型信息删除的过程,以确保与Java1.4及之前的版本保持兼容

泛型参数在运行时会被替换为其上界(通常是Object),这样一来在运行时无法获取泛型的实际类型。

作用:泛型擦除确保了Java代码的向下兼容性,即可以与旧版本的Java代码兼容,为了让使用泛型的代码在不同版本的Java运行时环境中都可以正常工作。又由于泛型类型信息在编译时期被擦除了,因此运行时无法获取泛型信息,这样就不能创建泛型类型的数组或对泛型类型使用instanceof检查

示例:

public <T> void printList(List<T> list) {for (T element : list) {System.out.println(element);}
}

编译后的代码类似于:

public void printList(List list) {for (Object element : list) {System.out.println(element);}
}

类型T会被擦除成Object

扩展知识

为什么Java泛型的实现是类型擦除?

回答重点提到了主要原因是为了向下兼容,即兼容Java5之前编译的class文件。

例如Java1.2上正在跑的代码,可以在Java1.5上的JRE上运行

也是因为需要向下兼容,才使得Java实现的是伪泛型

我从现有的实现倒推伪泛型的设计可能思路(个人瞎掰的,做个参考即可)

是这样的:

  1. 这Java5以前的版本在线上已经有很多应用在跑了,如果我的Java5不能兼容,没人用啊
  2. 泛型毕竟是加一个约束,以前的代码没有这个约束啊,该如何兼容?
  3. 有了,要不我在编译器上动手动脚,在编译的时候识别和约束泛型,然后编译过了就把泛型的信息擦除了。这样运行的时候就没有约束了,跟之前的版本就没什么区别了。

参考网上的解释:

这说明,写Java的也是程序员,也是要发版有上线需求的

为什么运行期通过反射可以获得类型?

public class GenericTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("hello");String s = list.get(0);}
}

看字节码 

从反编译看生成的字节码文件能看到,new的List没有保存泛型,所以是被擦除了

下面有一步checkcast强转为String,可是Java代码中不需要写强转呢?

因为编译器隐形的帮我们插入了强转的代码所以不需要我们写

再看标题:既然擦除了类型,为什么运行期还能通过反射获取类型?

答案就藏在class文件中

看下面代码:

获取泛型类型

public class GenericTest {public List<String> list;public static void main(String[] args) throws Exception{Field field = GenericTest.class.getField("list");Type type = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];System.out.println(type);}
}

javap -v,可以看到字节码里记录了泛型类型信息,所以编译器虽然擦除了泛型类型,也记录了泛型信息,自然能通过反射获取

由于静态记录在了字节码中,所以局部变量这种存在栈中的泛型类型,通过反射就无法获取

只有三种情况可以通过反射获取泛型类型:

  • 成员变量的泛型
  • 方法入参的泛型
  • 方法返回值的泛型
  • 类的泛型

http://www.lryc.cn/news/508118.html

相关文章:

  • 使用ssh命令远程登录服务器的两种便捷方式:简化ssh命令、创建bat文件
  • access数据库代做/mysql代做/Sql server数据库代做辅导设计服务
  • 第十七届山东省职业院校技能大赛 中职组“网络安全”赛项任务书正式赛题
  • Android学习(五)-Kotlin编程语言-面向对象中的 继承-构造函数-接口三模块学习
  • 滑动窗口 + 算法复习
  • 贪心算法 greedy
  • 基于python的家教预约网站-家教信息平台系统
  • 基于深度学习多图像融合的屏幕缺陷检测方案
  • MySQL基础笔记(三)
  • 【JetPack】WorkManager笔记
  • docker 安装 ftp
  • 5.C语言内存分区-堆-栈
  • 传统CV算法——基于opencv的答题卡识别判卷系统
  • 国产 HighGo 数据库企业版安装与配置指南
  • 「Mac畅玩鸿蒙与硬件46」UI互动应用篇23 - 自定义天气预报组件
  • Springboot @Transactional使用时需注意的几个问题
  • 数字经济下的 AR 眼镜
  • 力扣150题
  • 剑指offer搜索二维矩阵
  • 如何设置浏览器不缓存网页
  • Iris简单实现Go web服务器
  • 后端项目java中字符串、集合、日期时间常用方法
  • 【Spring事务】深入浅出Spring事务从原理到源码
  • vue.js滑动到顶便锁定位置
  • EdgeX Core Service 核心服务之 Core Command 命令
  • 掌握常用HTML标签:创建个人简介网页
  • 音视频学习(二十五):ts
  • 10. 虚拟机VMware Workstation Pro下共享Ubuntu和Win11文件夹
  • 单元测试mock框架Mockito
  • Python从0到100(七十八):神经网络--从0开始搭建全连接网络和CNN网络