泛型
一,泛型概念:
泛型,“泛”为广泛之意,“型”为类型之意。就是广泛适用的类型。
其中准确的说法是:参数化类型,如同实参传参给形参的方式,将类型当成一个参数进行传递。
二,泛型分类
1,泛型类
2,泛型方法
3,泛型接口
使用方式:
二,泛型类
定义泛型类:
权限修饰符 class 类名<类型参数>{
T test; //全局变量
}
public class Test<T>{
T mytest;
}
public static void main(String[] args){
Test<String> test1 = new Test<>();
Test<Integer> test2 = new Test<>();
}
注意:
“T”指的是类型参数,它可以为任意字母或者字符串,但建议使用公认统一的方式定义类型参数,如下:
- T 代表一般的任何类。
- E 代表 Element 的意思,或者 Exception 异常的意思。
- K 代表 Key 的意思。
- V 代表 Value 的意思,通常与 K 一起配合使用。
- S 代表 Subtype 的意思,文章后面部分会讲解示意。
三,泛型方法
定义泛型方法:
权限修饰符 <参数化类型> 返回值 方法名(参数化类型 形参){
方法体;
}
示例:
public class Test(){
publib <T> void DemoTest(T t){
方法体;
}
}
注意:
其一:泛型类和泛型方法中的“”被称为类型参数,泛型方法中的的“(T)”被称为参数化类型,
其二:泛型方法中声明的类型参数可以作为方法的返回值类型。
其三:泛型类与泛型方法共存问题,当两者共存时,泛型类中的类型参数与泛型方法中的类型参数没有联系,泛型方法始终以自己定义的泛型参数为准。
示例一:
pulic <T> T demoTest(T t){
方法体;
}
实例二:
public class Test<T>{
/**
*方法demoTest02的<T>与类Test的<T>没有联
*/
public void demoTest01(T t){
return null;
}
public <T> T demoTest02(T t){
return null;
}
}
四,泛型接口(与泛型类类似,不多加赘述)
定义泛型接口:
修饰符 Interface 接口名 <类型参数>{
接口体;
}
示例:
public Interface DemoInterface<T>{
接口体;
}
泛型通配符
一,泛型通配符
通配符概念:
子类与父类具有继承关系,为了处理子父类范围内的数据类型,因此就有通配符,通配符的出现是为了指定泛型中的类型范围。
二,通配符分类
1,<?>无限定通配符
2,<? extends T>上限通配符
3,<? super T>下限通配符
三,使用方式
一,无限定通配符
public void domeTest(Collection<?> collectio{
//只能调用 Collection 中与类型无关的方法,
只有读的功能 。
}
二,上限通配符
public void domeTest(Collection<? extends A> collection{
//表示Collection接受A类以及A的子类的类型,只有读的功能。
}
三,下限通配符
public void domeTest(Collection<? super B> collection){
//表示Collection接受B类以及B的超类,具有写的功能。
}
泛型擦除
泛型擦除概念
泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除
金典例题:
List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
System.out.println(l1.getClass() == l2.getClass());
//结果: 返回true。
分析:因为List和List在JVM中的Class都是List.class。泛型信息被擦除了。
结论:在泛型类被类型擦除的时候,之前泛型类中的类型参 数部分如果没有指定上限,如 则会被转译成普通的 Object类型,如果指定了上限如 则类型参数就被替换成类型上限。