0%

Java 泛型

简介

泛型的本质是参数化类型, 泛型提供了编译时类型的安全检测机制, 该机制允许程序在编译时检测非法的类型, 比如要实现一个能够对字符串 (String) , 整形 (Int) , 浮点型 (Float) , 对象 (Object) 进行大小比较的方法, 就可以使用 Java 泛型

在不使用泛型的情况下, 我们可以通过引用 Object 类型来实现参数的任意化, 因为在 Java 中 Object 类是所有类的父类, 但在具体使用时需要进行强制类型转换, 强制类型转换要求开发者必须明确知道实际参数的引用类型, 不然可能引起前置类型转换错误, 在编译期无法识别这种错误, 只能在运行期检测这种错误 (即只有在程序运行出错时才能发现该错误) , 而使用泛型的好处是在编译期就能够检查类型是否安全, 同时所有强制性类型转换都是自动和隐式进行的, 提高了代码的安全性和重用性

泛型标记

标记 类型 说明
E Element 在集合中使用, 表示在集合中存放的元素
T Type 表示 Java 类
K Key 表示键, 如 Map 中的 key
V Value 表示值, 如 Map 中的 value
N Number 表示数值类型
? 表示不确定的 Java 类型

类型通配符使用 ? 表示所有具体的参数类型, 例如 List<?> 在逻辑上是 List<String>, List<Integer> 等所有 List< 具体类型实参 > 的父类

泛型限定

泛型上限: <? extends T>, 通配符所代表的类型是 T 类的子类或者接口 T 的子接口
泛型下限: <? super T>, 通配符所代表的类型是 T 类型的父类或者父接口

类型擦除

在编码阶段采用泛型时加上的类型参数, 会被编译器在编译时去掉, 这个过程就被称为类型擦除, 因此, 泛型主要用于编译阶段, 在编译后生成的 Java 字节代码文件中不包含泛型中的类型信息, 例如, 编码时定义的 List<Integer>List<String> 在经过编译后统一为 List, JVM 所读取的只是 List, 由泛型附加的类型信息对 JVM 来说是不可见的

过程如下

  • 查找用来替换类型参数的具体类 (该具体类一般为 Object)
  • 如果指定了类型参数的上界, 则以该上界作为替换时的具体类
  • 把代码中的类型参数都替换为具体的类