问题
- 存放多个(不同类型)对象,容易出现转型错误ClassCastException
解决办法
- 引入泛型:存放多个对象(限定一种类型),不需要转型,没有转型错误
简介
- 泛型:jdk1.5推出的特性
- 编写的代码可以被很多不同类型的对象所重用
- 泛型类:ArrayList,HashSet,HashMap等
- 泛型方法:Collections.binarySearch等
- 泛型接口:List,Iterator等
- 泛型的本质:参数化类型,避免类型转化,代码可复用
自定义泛型
- 泛型类
具有泛型变量的类,在类名后用<T>代表引入类型,多个字母表示多个引入类型,如<T,U>等,引入类型可以修饰成员变量/局部变量/参数/返回值 - 泛型方法
具有泛型参数的方法,该方法可在普通类/泛型类中,在修饰符后,返回类型前 - 泛型接口
和泛型类相似,在类名后加,T用来指定方法返回值和参数,实现接口时,指定类型
泛型类型限定
- 泛型限定
约定T必须是Comparable的子类,extends固定,后面可以多个,以&拼接,如<T extends Comparable & Serializable>,extends限定可以有多个接口,但只能一个类,且类必须排第一位,逗号隔开参数,<T extends File & Cloneable,U extends Serializable> - 泛型继承原则
Pair<S> 和Pair<T>没有任何关系,无论S和T之间是什么关系
泛型类可以扩展或实现其他的类,如ArrayList实现List - 上限界定符,Pair<? extends S>
- Pair能接收的参数类型是S自身或子类
- 只能get/不能set,编译器只能保证出来的类型,但不保证放入的对象是什么类型
- 下限界定符,Pair<? super S>
- Pair能接收的类型参数,是S的自身或超类
- 只能set/不能get,编译器保证放入的是S本身或超类,但不保证出来是什么具体类型
- 无限定类型通配符
Pair<?>,无限定通配符,表示任意类型 - 泛型PECS原则
Producer Extends,Consumer Super
要从泛型类型读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends,泛型类是生产者,往外输出东西)
如果要向泛型类写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super,泛型类是消费者,往内增加东西)
如果既想写入又想读出,那就不用通配符
泛型实现的本质和约束
- jdk的版本是向后兼容的,即低版本的Class文件可以在高版本的jdk上运行,因此,jvm里面没有泛型对象,而是采用类型擦除技术,只有普通的类和方法
- 类型擦除
擦除泛型变量,替换为原始类型,无限定为Object,有限定则为第一个类型,擦除泛型变量后,为了保证类型的安全性,需要自动进行类型转换,虚拟机也会用合成桥方法来保持方法多态 - 泛型的约束
java类型协变和逆变
- 类型变化关系
A、B是类型,f(.)表示类型转换,≤表示继承关系,如A≤B,表示A继承于B - java类型变化
数组是协变的
String是Object的子类,String[]是Object[]的子类
java的原始泛型是不变的
String是Object的子类,List和List