泛型概念
泛型是什么
可以将类型作为参数进行传递,本质上是类型参数化
优点
-
消除强制类型转换。使用时直接得到目标类型,消除许多强制类型转换
-
类型安全。在编译的时候检查数据类型的安全,可以检查出因 Java 类型不正确导致的 ClassCastException 异常
类型擦除
泛型值存在于编译期,代码在进入虚拟机后泛型就会被擦除掉,这个特性叫做类型擦除
-
如果泛型没有设置类型上限,那么将泛型转化成Object类型
-
设置了类型上限,那么将泛型转化成他的类型上限。
-
如果有多个类型上限。使用第一个作为原始类型(T extends Demo1 & Demo2)原始类型为Demo1
泛型常见的字母说明
- T Type 标识类型
- K,V 代表键值对中的key和value
- E 代表Element 通常在集合中使用
- N 代表Number 数字
- ? 无限通配符,表示的是未知类型,表示不关心或者不能确定实际操作的类型,一般配合容器类使用。
?和Object的区别
?表示未知类型。Object表示任意类型。 Object在使用时需要强制转换为想要的类型。编译器只有在运行时才知道类型转换是否出现异常。
常用方法
-
TypeVariable<?>[] getTypeParameters() 获取声明的泛型变量类型清单。
-
Type[] getGenericParameterTypes()返回方法的参数信息,如果参数是泛型类型的,会返回泛型的详细信息
-
Type getGenericReturnType()返回方法的返回值类型,如果返回值是泛型的,会包含泛型的详细信息。
-
Type getRawType()返回参数化类型中的原始类型,比如:List的原始类型为List,UserMapper原始类型为UserMapper,也就是<符号前面的部分
-
Type[] getOwnerType()返回当前类型所属的类型。Map接口与Map.Entry接口,Map接口是Map.Entry接口的所有者。
-
Type[] getActualTypeArguments()获取泛型类型中的类型列表,就是<>中包含的参数列表Map泛型类型中包含2个类型:Integer和String
-
D getGenericDeclaration()获取声明该泛型变量的原始类型
-
Type getGenericSuperclass()返回父类的类型信息,如果父类是泛型类型,会返回超类中泛型的详细信息,
-
Type[] getBounds()获取泛型变量类型的上边界,如果未明确什么上边界默认为Object。
泛型变量
泛型变量在类或方法上定义。泛型变量类型使用TypeVariable表示
类中定义泛型变量
- 泛型变量需要在类名后的<>中定义
- 可以定义多个泛型,用 “,”隔开
- 通过extends指定上边界,默认为Object。多个上边界之间用“&”隔开
语法
class 类名<泛型变量1,泛型变量2,泛型变量3 extends 上边界1,泛型变量4 extends 上边界类型1 & 上边界类型2 & 上边界类型3>
class genericTest<T1, T2 extends Integer, T3 extends DemoI1 & DemoI2>
方法中定义泛型变量
语法
方法修饰符 <泛型变量1,泛型变量2,泛型变量3 extends 上边界1,泛型变量4 extends 上边界类型1 & 上边界类型2 & 上边界类型3> 方法名称(参数1类型 参数1名称,参数2类型 参数2名称)
public <T1, T2 extends Integer, T3 extends DemoI1 & DemoI2> T3 m1(T1 t1, T2 t2, T3 t3, String s) { return t3;}
泛型变量类型在java中使用TypeVariable表示,前3个参数都是泛型变量类型的,所以最后他们的信息都可以使用TypeVariable接口获取,最后一个参数是String类型的,这个是非泛型类型,使用Class类型来表示。
泛型类型
-
泛型类型可以作为方法的参数、方法的返回值、泛型类
-
<>中的泛型的实际参数列表,可以有多个,可以是任意类型的,比如:String类型、自定义类型、泛型变量类型、泛型通配符类型
-
泛型类型的信息在java中使用ParameterizedType接口来表示
具体类型 <类型1,类型2,类型3> public class C1 { public List m1(List list) { //对list做一些操作 return list; } }
泛型类
类修饰符 类名<类型1,类型2,类型n>{}
public class HashMap<K,V> {}
边界
当我们不指定或者不关心操作类型,但是又想进行一定范围限制的时候,我们可以通过添加上限或下限来起到限制作用。
上边界<? extends T>
-
定义了上限,只有读的能力。此方式表示参数化的类型可能是所指定的类型,或者是此类型的子类。如果传入的类型不是 T 或者 T 的子类,编辑不成功
-
用于灵活读取,使得方法可以读取T 或 T 的任意子类型的容器对象。
下边界<? super T>
-
定义了下限,有读的能力以及部分写的能力,子类可以写入父类。此方式表示参数化的类型可能是指定的类型,或者是此类型的父类。如果传入的类型不是T 或者T 的父类,编辑不成功
-
用于灵活写入或比较,使得对象可以写入父类型的容器,使得父类型的比较方法可以应用于子类对象。
注意:
-
要从泛型类取数据时,用 ? extends 通配符
-
要往泛型类写数据时,用 ? super 通配符
-
既要取又要写,就不用通配符(即extends与super都不用)。
-
不能同时声明泛型通配符上界和下界