Java 基础 - Java为什么要类型擦除?
总结
一句话:为了兼容JDK 5 之前(有泛型功能之前)的项目,否则有大量代码修改的工作。
1-“真泛型”是怎么操作的?
- 若 Java 语言实现"真泛型",对泛型类型(泛型类、泛型接口)、泛型方法的名字使用特别的编码,例如将 Factory<T> 类生成为一个名为 “Factory@@T” 的类,这种特别的编码后的名字将被编译器识别,作为判断是否为泛型的依据。
- 如果编译时发现有对 Factory<String> 的使用,则将 “Factory@@T” 的所有逻辑复制一份,新建 “Factory@String@” 类,将原本的占位符 T 替换为 String 。然后在编译 new Factory<String>() 时生成 new Factory@String@() 即可。
2-“真泛型”会导致什么后果?
- 2.1 大规模的代码修改
- 假设A调用B1 lib,然后B1 lib迁移到了Java 5,并使用了泛型。那么A 也必须升级到Java 5,并修改代码。在 Java 中不支持高版本的 Java 编译生成的 class 文件在低版本的 JRE 上运行,如果尝试这么做,就会得到 UnsupportedClassVersionError 错误。如下图所示:
2.2 非泛型类型和泛型不匹配
在 A 项目中,A 项目引用了 B1 lib 中的 ArrayList(用 list 变量记录),那么假设 A 项目升级到 Java 5 后,还是引用的 B1 lib,那么必然会出现如下这种情况:
下述代码中,A 项目将泛化后 ArrayList<T> 的传递给了 B1 lib 中的 ArrayList。
ArrayList list = new ArrayList<String>();
- 左边:B1 lib 中的老版本 ArrayList
- 右边:A 项目 中的新泛型版本 ArrayList<T>
这种情况的出现,会导致一个问题。就是 b1 项目中的 ArrayList 是不知道 A 项目中的 Arraylist 已经泛型化了的,那么如何保证泛型化后的 ArrayList(也就是ArrayList<T>)与老版本的 ArrayList 等价呢?
如果按照我们之前讲解的 “真泛型” 思路来处理 Java 的泛型, 那么 new ArrayList<String>() 实际会被替换为 new ArrayList@String@(),那么实际运行代码是这样:
ArrayList list = new ArrayList@String@()
从代码逻辑上来看,根本就跑不通。因为 ArrayList 与 ArrayList@String@ 根本就不是同一类, 那怎么办呢?
最为直接的解决方案就是,不再为参数化类型创造新类了,同时在编译期间将泛型类型中的类型参数全部替换 Object(因为不创建新类了,那么在泛型类中的 T 对应的类型,只能用 Object 替换)。
3-为了兼容JDK 5 之前的项目
通过编译器的”魔法“,Java 就解决了处理泛型兼容老版本的问题。
//编译器的代码 Node node = new Node<String>(); //编译后的代码 Node node = new Node();
参考文献
作者:AndyJennifer
链接:https://juejin.cn/post/6844904134273925134
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?