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

原文地址:https://www.cnblogs.com/frankcui/p/14373910.html