JAVA泛型之我见

java在1.5之前是没有泛型的,是后来加的,加了之后用起来感觉和C++的泛型差不多,但是原理是不一样的,C++的泛型是有宏演变而来的,虽然对泛型的处理不包含在预编译阶段

,但是对泛型的处理也是简单的替换操作,也就是说泛型就相当于一个模版,在编译过后,编译器会帮你生成一个个具体的类。

java不同,java的模版类就是一个类,里面的参数T 不过是它的一个成员变量而已,只不过在构造示例的时候,以模版类型的方式传递。举个例子说:

1
class Template<T>{}

它就是一个类,Template<String>(); 就是一个实例,String只不过是构造方法(可以这样理解)的一个参数而已,java编译器不会帮你生成一个新的类。
java的泛型在设计之初就是因为Object当作“任意”类型的时候,编译阶段无法进行类型检查,而引入了一个T参数,让你在构造对象的时候,强制你指定类型,它就可以做一些类

型检查了,你也可以进行对一个“任意”类型的功能实现,达到代码重用的目的。

对于Template<T> 这样的类型的实现子类,例如:

1
2
class MyTemplate1 extend Template<String>{}
class MyTemplate2 extend Template<Integer>{}

对于MyTemplate1和MyTemplate2的父类都是Template.class 但是又有所不同,上文说过Template本身就是一个类型,不是一个类的模版。所以为了描述MyTemplate1和MyTemplate2

的父类型的不同。
jdk又引入了一个ParameterizedType类型,它和Class 一样继承于Type类型。

它包含了一个泛型实例( Template<Integer>())的类型信息。
如果你想得到一个这样的类型,你只有通过泛型类型的子类得到,也就是说MyTemplate1的父类型才是这样的类型。
你通过Template<Integer> instance = new Template<Integer>()是得不到的这样的类型的。
你只有通过MyTemplate2的才可以得到:

1
ParameterizedType type = (ParameterizedType)MyTemplate2.class.getGenericSuperclass();

或者是通过一个匿名类

1
ParameterizedType type = new Template<Integer>(){}.getClass().getGenericSuperclass();

可以通过ParameterizedType 的getActualTypeArguments()方法 拿到里面的Integer类型。

所以你在用各种json工具的时候,你会发现他们当把Json转成一个对象的时候,它都要求你传入一个Type类型,而不是一个Class类型
因为一个Class类型是无法描述Map<String,String>()这种类型全部信息的,那些json工具是无法通过一个Map.class帮你把把字符串转成一个具体的map的。
而且Map<String,String>()也不是一个类,
这时你可以传入一个ParameterizedType类型。

这样你就可以理解为什么像fastjson那样会提供下面这样一个类了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class TypeReference<T> {
 
private final Type type;
 
protected TypeReference(){
Type superClass = getClass().getGenericSuperclass();
 
type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
 
public Type getType() {
return type;
}
 
public final static Type LIST_STRING = new TypeReference<List<String>>() {}.getType();
}

解释一下 new TypeReference<List<String>>() {} 是TypeReference<List<String>>的一个匿名子类。
它的getGenericSuperclass() 就是TypeReference<List<String>> 这种类型(ParameterizedType)。
它的参数也就是List<String> 也是一个ParameterizedType类型。

留言

提示:你的email不会被公布,欢迎留言^_^

*

验证码 *