泛型
前言
在 上一篇文章 中我们学习了代理相关的技术,知晓了代理有静态和动态之分,且静态代理与动态代理各有优劣,笔者也分享了自己的使用经验。
Retrofit
灵活运用了动态代理技术为我们创建了优秀的 http
请求框架,可以说动态代理是 Retrofit
的灵魂与核心,但是在 Retrofit
中也大量使用了反射与泛型,所以今天我们主要学习下泛型的一些基础知识,为我们继续学习 Retrofit
打下知识储备。
泛型概述
众所周知,Java 的泛型是伪泛型,其会在编译时被擦除,在运行时不存在任何与泛型类型相关的信息。我们常用的就是集合类型了,例如 List<String>
在运行时就只有 List
了。
泛型为我们提供了编译期的类型安全。
出于安全原因,泛型默认不支持型变,因此 Java 提供了通配符上限,通配符下限和无限定通配符。
通配符上限:协变
在 Java 中使用 extends
关键字表示通配符上限。
如果 S 是 F 的子类,那么 List<S>
相当于是 List<? extends F>
的子类,比如 Integer
是 Number
的子类,那么 List<Integer>
相当于 List<? extends Number>
的子类,上述这种型变方式称为泛型的协变。
对于支持协变的泛型集合,我们只能从集合中取出元素,但是不能向集合中添加/修改元素( null
除外),因为取出元素时可以保证元素的类型上限,而添加/修改元素时无法确定元素的具体类型。
因此,支持协变的泛型,一般只能返回元素,不能注入元素( null
除外)。
通配符下限:逆变
在 Java 中使用 super
关键字表示通配符下限。
如果 S 是 F 的子类,那么 List<F>
反而相当于是 List<? super S>
的子类,比如 Integer
是 Number
的子类,那么 List<Number>
相当于 List<? super Integer>
的子类,上述这种型变方式称为泛型的逆变。
对于支持逆变的泛型集合,我们只能往集合中添加/修改元素,但是不能从集合中取出元素,因为添加/修改元素时可以保证元素的类型下限,而取出元素时无法确定元素的具体类型。
因此,支持逆变的泛型,一般只能注入元素,不能返回元素。
无限定通配符
在 Java 中使用 ?
关键字表示无限定通配符。无限定通配符一般用于在不确定具体类型时。
支持无限定通配符的泛型,一般只能返回元素,不能注入元素( null
除外)。
总结
- 泛型为我们提供了编译期的类型安全。
- 支持协变的泛型,一般只能返回元素,不能注入元素(
null
除外)。 - 支持逆变的泛型,一般只能注入元素,不能返回元素。
- 支持无限定通配符的泛型,一般只能返回元素,不能注入元素(
null
除外)。