Java中的泛型
1、为什么要使用泛型?
(1)适用于多种数据类型执行相同的代码,利于封装(如,封装Base类、统一的适用于recycleview的adapter等)
(2)泛型中的类型在使用的时候,直接指定即可,不需要进行强制转换。数据转换是很容易带来数据异常的,尤其是当服务端传过来的数据与我们接收的数据类型不同的时候。
2、泛型类、泛型接口、泛型方法?
泛型方法
引入一个类型变量T(其他大写字母都可以,不过常用的就是T,E,K,V等等),并且用<>括起来,并放在类名的后面。泛型类是允许有多个类型变量的。例如:
一个类型变量
两个类型变量
泛型接口
泛型接口与泛型类的定义基本相同
而实现泛型接口的类有两种实现方法:
(1)未传入泛型参数时,那么该类也属于泛型类
那么在new出该实例对象时,需要指定具体类型
(2)在实现泛型接口时,传入泛型参数。
那么在new出该类的实例时,与普通的类就没区别了。
泛型方法
public代表修饰符,<T>表示泛型方法,紧跟后面的T表示返回值。
泛型方法是在调用方法的时候指明泛型的具体参数类型,泛型方法可以在任何场景中使用,包括普通类和泛型类。但是在泛型类中定义普通方法和泛型方法是有区别的:
普通方法:
泛型方法:
关键点:<T>
3、限定类型变量
有时候我们需要对变量类型进行约束。比如我们定义一个泛型方法:
如何才能够保证传进来的a、b两个参数一定有compareTo方法呢?那么我们就要对T进行约束,保证传进来的T参数的类型实现了Comparable类
T extends Comparable表示,传进来的实例对象必须实现了Comparable类,否则将发生编译错误
extends左右都允许有多个,如T,V extends Comparable & Serializable
注意限定类型的时候,只允许有一个类,允许多个接口,如果所限定的类型包含类和接口,那么类要放在最前面,也就是紧跟extends之后的第一个要放类。
类型限定既可以放在泛型方法上,也可以用在泛型类上
T super XXX跟 extends用法一样,只不过super表示传入的类型T只能是XXX或XXX的父类,最高为object类
4、泛型中的约束和局限性
现在我们有泛型类
(1)不能用基本类型实例化
(2)运行时,类型查询只适用于原始类型
因为类型擦除,java虚拟机中的对象并没有泛型类这一说,instanceof
和 getClass()
只能查询到原始类型, 具体的泛型类型时无从得知的。
(3)泛型类的静态上下文中类型变量失效
不能在静态域或静态方法中使用泛型。因为泛型是需要我们在创建对象的时候才知道是什么类型,而对象创建过程中,代码的执行先后顺序是最先执行static部分,然后才是构造函数等。
因此,在对象初始化之前static部分的代码已经执行,而此时的static块并不知道到底是什么类型,因为这个时候我们的对象还没初始化。
(4)不能创建参数化类型的数组
例如 Restrict<Double> array = new Restrict<Double>[10]
是错误的,
我们只能声明Restrict<Double>[] array;
(5)不能实例化类型变量
(6)不能补货泛型类的实例
但可以这样
5、泛型类型的继承规则
现在我们有一个类和子类
有一个泛型类
Pair<Employee>和Pair<Worker>之间没有任何关系
但是泛型类之间可以继承和扩展其他泛型类,例如:List和ArrayList
泛型类和泛型接口