0x5、Java有界泛型类型
如果不对泛型类型做限制,泛型类型可实例化为任意类型的话,可能会产生某些安全隐患。为了限制允许实例化的泛型类型,可在泛型类型后追加 extends 父类型,代码示例如下:
有界泛型类型在一定程度上限制了泛型类型,提高了程序的安全性;因为定义了边界,所以可以调用父类或父接口的方法。
0x6、Java通配符
Java泛型本身「不变」的,不支持「协变」和「逆变」,是通过通配符(?)来实现的
① <T>与<?>的区别
<T>「泛型标识符」用于泛型「定义时」可理解为「形参」;
<?>「通配符」用于泛型「实例化时」可理解为「实参」。
代码示例如下:
② 各种通配符
- 上边界通配符<? extends 父类型>
实例化时可确定为「父类型的未知类型」故「只能读不能写」,从而使得类型是「协变的」。
代码示例如下:
- 下边界通配符:<? super 子类型>
实例化时可确定为「子类型的未知类型」故「只能写不能读」从而使得类型是「逆变的」。
(不能读指的是不能按照泛型类型读取)<代码示例如下:
上边界通配符只能读不能写,改为下边界通配符
- 无限定通配符:<?>
等同于上边界通配符<? extends Object>,「类型完全未知」故「只能读不能写」从而使得类型是「不变的」。
Tips:看完这里,估计有部分读者还是有点懵逼,这里总结下:
- 不变 → 子类和父类没关系,正常存取,不用通配符就好,Java集合本身就是不变的;
- 协变 → A是B的子类型,泛型<A>也是泛型<B>的子类型,只想取,用extends。
- 逆变 → A是B的子类型,泛型<B>也是泛型<A>的子类型,只想存,用super。
- PECS法则(Producer Extends,Consumer Super) 参数化类型是一个生产者,则使用:<? extends T> 如果它是一个消费者,则使用<? super T>