2.44 泛型

less than 1 minute read

引入泛型

  • 类型安全
    • 泛型主要目标是提高Java程序的类型安全
    • 编译器可检查出因Java类型不正确导致的ClassCastException异常
    • 符合越早出错代价越小原则
  • 消除强制类型转换
    • 直接得到目标类型, 消除许多强制类型转换
    • 代码可读性高
  • 潜在的性能收益
    • 由于泛型的实现方式,支持泛型(几乎)不需要 JVM 或类文件更改
    • 所有工作都在编译器中完成
    • 编译器生成的代码跟不使用泛型(和强制类型转换)时所写的代码几乎一致,只是更能确保类型安全而已

泛型使用方式

  • 泛型类
    • 泛型类和普通类的区别就是类名后有类型参数列表, <E><K, V>
  • 泛型接口
    • 泛型接口在接口名后添加类型参数, <E><K, V>
  • 泛型方法

泛型通配符

  • 无限通配符
    • 不确定或者不关心实际要操作的类型,可以使用无限制通配符(尖括号里一个问号,即 <?> ),表示可以持有任何类型。
  • 上界通配符<? extends E>
    • List<? extends Fruit>,我们可以把它读作:一个类型的 List, 这个类型可以是继承了 Fruit 的某种类型。注意,这并不是说这个 List 可以持有 Fruit 的任意类型。只能get()不能add(), 适用于读取场景
  • 下界通配符<? super E>
    • List<? super Apple>,它表示某种类型的 List,这个类型是 Apple 的基类型, 这个类型肯定是 Apple 的父类型, 因此,我们可以知道向这个 List 添加一个 Apple 或者其子类型的对象是安全的,这些对象都可以向上转型为 Apple

泛型的类型擦除

  • 当编译器对带有泛型的java代码进行编译时,它会去执行类型检查和类型推断,然后生成普通的不带泛型的字节码,这种普通的字节码可以被一般的 Java 虚拟机接收并执行,这在就叫做 类型擦除(type erasure)。
  • Java 编辑器会将泛型代码中的类型完全擦除,使其变成原始类型。当然,这时的代码类型和我们想要的还有距离,接着 Java 编译器会在这些代码中加入类型转换,将原始类型转换成想要的类型。这些操作都是编译器后台进行,可以保证类型安全
  • 泛型擦拭后, 如List<String> list = new ArrayList<>();list.add("123);list.get(0).intern();编译后String会被擦拭, list.get(0)会进行类型转换, 即(String)list.get(0)

参考