一、为什么要使用泛型?
1. 在编译时进行更强的类型检查。


上例中,指定List只能添加String,当加入非String类型时编译时就会报错。当我们不指定类型时,list默认的类型为Object类型,我们可以同时添加String和Integer两种对象类型,但是当我们取数据时,由于数据类型未知很容易报java.lang.ClassCastException异常。
2.消除类型转换

3.可以实现通用代码逻辑

二、泛型类型
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?
顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
引入一个类型变量T(其他大写字母都可以,不过常用的就是T,E,K,V等等),并且用<>括起来,并放在类名的后面。泛型类是允许有多个类型变量的。
1. 泛型类


2. 泛型接口

未传入泛型实参时:

在new出类的实例时,需要指定具体类型:

2、传入泛型实参

在new出类的实例时,和普通的类没区别。
3. 泛型方法

三、泛型约束和局限
1.不能使用基本类型实例化参数,需要使用基本类型包装类
2.static修饰的静态类和方法不能使用泛型
3.不能创建泛型类数组,但是可以定义
Generator [] generator;//可以使用
Generator<String>[] generator = new Generator<String>[3];//不允许
4.不能实例化参数类型
T data= new T();//不允许
5.不能捕获泛型类异常,但可以throw
6. 无法将Casts或instanceof与参数化类型一起使用。
7. 无法重载每个重载的形式参数类型都擦除为相同原始(raw)类型的方法
public class Example {
public void print(Set<String> strSet) { }
public void print(Set<Integer> intSet) { }//两个方法为同一个参数
}
四、什么是泛型檫除
Java语言的泛型采用的是擦除法实现的伪泛型,泛型信息(类型变量、参数化类型)编译之后通通被除掉了。在类型擦除过程中,Java编译器将擦除所有类型参数,如果类型参数是有界的,则将每个参数替换为其第一个边界;如果类型参数是无界的,则将其替换为Object 。

上例中,ArrayList<String>和ArrayList<Integer>是不同的类型,编译后经过泛型檫除,都转为ArrayList<Object>,所以返回为true。
编译器会进行泛型擦除。
(1)实际上擦除的只是参数和自变量的类型,但会将泛型信息保存到Signature中,我们可以通过匿名类获取。
(2)类结构相关的信息(属性,类,接口,方法签名)即元数据会保存下来,可以通过反射直接获取到的。
五、泛型限制
使用泛型时,可以使用extends关键字对泛型T进行限制。例如,对数字进行操作的方法可能只希望接受Number 或其子类的实例。

前面的示例说明了使用带单个限定的类型参数,但是一个类型参数可以具有多个限定。

需要注意:限制是只能继承一个类,并且需要在extends关键字的后面,然后实现多接口
六、通配符?
1.上限统配符<? extends XXX>(只读)
可以使用上限通配符来放宽对变量的限制, 例如,假设你要编写一种适用于List , List 和List 的方法;可以使用上限通配符来实现。

使用上限通配符,主要用于安全地访问数据,可以访问X及其子类型,并且不能写入非null的数据。
2.下限通配符
下限通配符将未知类型限制为特定类型或该类型的超类型。

使用下限通配符,主要用于安全地写入数据,可以写入X及其子类型。
3.无限定通配符?
表示对类型没有什么限制,可以把?看成所有类型的父类,如Pair< ?>;
比如:
ArrayList<T>al=new ArrayList<T>(); 指定集合元素只能是T类型
ArrayList<?>al=new ArrayList<?>();集合元素可以是任意类型,这种没有意义,一般是方法中,只是为了说明用法。
在使用上:
?getFirst() : 返回值只能赋给 Object,;
void setFirst(?) : setFirst 方法不能被调用, 甚至不能用 Object 调用;
参考文档:
官方文档:https://docs.oracle.com/javase/tutorial/java/generics/index.html
中文翻译:https://pingfangx.github.io/java-tutorials/java/generics/types.html
网友评论