跳至主要內容

泛型

guodongAndroid大约 3 分钟

前言

上一篇文章 中我们学习了代理相关的技术,知晓了代理有静态和动态之分,且静态代理与动态代理各有优劣,笔者也分享了自己的使用经验。

Retrofit 灵活运用了动态代理技术为我们创建了优秀的 http 请求框架,可以说动态代理是 Retrofit 的灵魂与核心,但是在 Retrofit 中也大量使用了反射与泛型,所以今天我们主要学习下泛型的一些基础知识,为我们继续学习 Retrofit 打下知识储备。

泛型概述

众所周知,Java 的泛型是伪泛型,其会在编译时被擦除,在运行时不存在任何与泛型类型相关的信息。我们常用的就是集合类型了,例如 List<String> 在运行时就只有 List 了。

泛型为我们提供了编译期的类型安全。

出于安全原因,泛型默认不支持型变,因此 Java 提供了通配符上限,通配符下限和无限定通配符。

通配符上限:协变

在 Java 中使用 extends 关键字表示通配符上限。

如果 S 是 F 的子类,那么 List<S> 相当于是 List<? extends F> 的子类,比如 IntegerNumber 的子类,那么 List<Integer> 相当于 List<? extends Number> 的子类,上述这种型变方式称为泛型的协变。

对于支持协变的泛型集合,我们只能从集合中取出元素,但是不能向集合中添加/修改元素( null 除外),因为取出元素时可以保证元素的类型上限,而添加/修改元素时无法确定元素的具体类型。

因此,支持协变的泛型,一般只能返回元素,不能注入元素( null 除外)。

通配符下限:逆变

在 Java 中使用 super 关键字表示通配符下限。

如果 S 是 F 的子类,那么 List<F> 反而相当于是 List<? super S> 的子类,比如 IntegerNumber 的子类,那么 List<Number> 相当于 List<? super Integer> 的子类,上述这种型变方式称为泛型的逆变。

对于支持逆变的泛型集合,我们只能往集合中添加/修改元素,但是不能从集合中取出元素,因为添加/修改元素时可以保证元素的类型下限,而取出元素时无法确定元素的具体类型。

因此,支持逆变的泛型,一般只能注入元素,不能返回元素。

无限定通配符

在 Java 中使用 ? 关键字表示无限定通配符。无限定通配符一般用于在不确定具体类型时。

支持无限定通配符的泛型,一般只能返回元素,不能注入元素( null 除外)。

总结

  1. 泛型为我们提供了编译期的类型安全。
  2. 支持协变的泛型,一般只能返回元素,不能注入元素( null 除外)。
  3. 支持逆变的泛型,一般只能注入元素,不能返回元素。
  4. 支持无限定通配符的泛型,一般只能返回元素,不能注入元素( null 除外)。