总结
一句话:为了兼容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
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。