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)
参考