1. 泛型概述
泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用。
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
2. 泛型在框架中使用
泛型在框架中及为常见,我们在使用各种框架的时候,都会使用到泛型,具体看下面的例子。
2.1 集合框架中使用泛型
这是最常见的泛型的使用场景,比如下面的代码
List<String> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
list1和list2虽然都是列表类型,但是列表里面存的数据可以是String,可以是Integer,也可以是自定义类型。集合中存放的数据,在定义的时候不能确定是什么类型,只有当使用集合时,才能确定放什么类型的数据。所以在集合的定义中,就用泛型来代表集合里面的数据。
2.2 fastjson框架中使用泛型
alibaba的fastjson很多人应该都用过,fastjson很多地方也用到了泛型,比如将json字符串转成对象,如下的例子
// 将userStr字符串映射成UserDto类
String userStr = "{id: '123', name: '张三'}";
UserDto userDto = JSON.parseObject(userStr, UserDto.class);
JSON类中,对parseObject方法的定义,如下
public static <T> T parseObject(String text, Class<T> clazz) {
return parseObject(text, clazz);
}
parseObject方法中的参数传递用到了泛型,要把json字符串转成什么类,在定义的时候并不知道,只有在用到的时候,才知道具体的类型。
3. 特性
泛型只在编译阶段有效。看下面的代码:
List<String> stringArrayList = new ArrayList<String>();
List<Integer> integerArrayList = new ArrayList<Integer>();
Class classStringArrayList = stringArrayList.getClass();
Class classIntegerArrayList = integerArrayList.getClass();
if(classStringArrayList.equals(classIntegerArrayList)){
Log.info("泛型测试,类型相同");
}
输出结果:泛型测试,类型相同。
通过上面的例子可以证明,在编译之后程序会采取去泛型化的措施。也就是说Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。
4. 泛型分类
泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法
4.1 泛型类
//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{
//key这个成员变量的类型为T,T的类型由外部指定
private T key;
public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
this.key = key;
}
public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
return key;
}
}
//泛型的类型参数只能是类类型(包括自定义类),不能是简单类型
//传入的实参类型需与泛型的类型参数类型相同,即为Integer.
Generic<Integer> genericInteger = new Generic<Integer>(10000);
//传入的实参类型需与泛型的类型参数类型相同,即为String.
Generic<String> genericString = new Generic<String>("猿码天地");
Log.info("泛型测试","key is " + genericInteger.getKey());
Log.info("泛型测试","key is " + genericString.getKey());
结果