目录
1. 泛型的使用场景和用处
1.1 使用场景
Java泛型这个特性是从JDK 1.5才开始加入的,因此为了兼容之前的版本,Java泛型的实现采取了“伪泛型”的策略,即Java在语法上支持泛型,但是在编译阶段会进行所谓的“类型擦除”(Type Erasure),将所有的泛型表示都替换为具体的类型(其对应的原生态类型)。
泛型的本质是为了参数化类型,在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
1.2 主要用处
-
适用于多种数据类型执行相同的代码(代码复用)。
-
泛型中的类型在使用时指定,不需要强制类型转换(类型安全)。
2. 泛型上下限
为了解决泛型中隐含的转换问题,Java泛型加入了类型参数的上下边界机制。
<? extends A>表示该类型参数可以是A(上边界)或者A的子类类型。编译时擦除到类型A,即用A类型代替类型参数。
这种方法可以解决开始遇到的问题,编译器知道类型参数的范围,如果传入的实例类型B是在这个范围内的话允许转换,这时只要一次类型转换就可以了,运行时会把对象当做A的实例看待。
3. 泛型中的类型擦除
Java泛型这个特性是从JDK 1.5才开始加入的,因此为了兼容之前的版本,Java泛型的实现采取了“伪泛型”的策略,即Java在语法上支持泛型,但是在编译阶段会进行所谓的“类型擦除”(Type Erasure),将所有的泛型表示都替换为具体的类型(其对应的原生态类型)。
3.1 类型擦除原则
1) 消除类型参数声明,即删除<>
及其包围的部分。
2) 根据类型参数的上下界推断并替换所有的类型参数为原生态类型:如果类型参数是无限制通配符或没有上下界限定则替换为Object,如果存在上下界限定则根据子类替换原则取类型参数的最左边限定类型(即父类)。
3) 为了保证类型安全,必要时插入强制类型转换代码。
4) 自动产生“桥接方法”以保证擦除类型后的代码仍然具有泛型的“多态性”。
3.2 擦除方式
1) 擦除类定义中的类型参数 - 无限制类型擦除。
当类定义中的类型参数没有任何限制时,在类型擦除中直接被替换为Object,比如<T>
和<?>
的类型参数都被替换为Object。
2) 擦除类定义中的类型参数 - 有限制类型擦除。
当类定义中的类型参数存在限制(上下界)时,在类型擦除中替换为类型参数的上界或者下界,比如<T extends Number>
和<? extends Number>
的类型参数被替换为Number
,<? super Number>
被替换为Object。
3) 擦除方法定义中的类型参数。
擦除方法定义中的类型参数原则和擦除类定义中的类型参数是一样的,这里以擦除方法定义中的有限制类型参数为例。