得先申明下,这篇文章应该不会有借鉴价值,我也只能是斗胆总结下。
为什么呢,因为这是我目前为止遇到问题最大的一部分,绕过去绕过来,可能是自己对泛型、类型学习都还不够,理解得很吃力很吃力。
代码部分来自博客:https://www.jianshu.com/p/73bb429b9a01
我实在懒得打注释了,解释就用文章的方式吧。
在开始介绍TypeParmeterResolver之前,得了解一下Type的知识:
Type是所有类型的父接口,它有四个子接口和一个实现类。
下面来看这些子接口和子类所代表的类型。
上面这些就是我很不熟的部分,所以给整个学习过程带来了挺大的麻烦。
那么咱回到TypeParameterResolver的介绍,他是一个工具类,提供了一系列静态方法来解析指定类中的字段、方法返回值或方法参数的类型。
也就是说,它露给了我们三个静态方法,分别对应解析字段类型、方法参数、方法返回值的类型解析。这三个方法里面内容差不多,通过指定类型的方式去调用resolverType方法,然后resolverType方法根据传过来的字段,再调用后边的方法。比如resolveFieldType:
/**
* 获取指定字段的实际类型,将泛型转换为实际类型
*
* @param field 字段
* @param srcType 运行时字段所属对象类型
* @return 如果field在声明的时候有泛型定义,这些泛型会被解析会运行时的实际类型
*/
public static Type resolveFieldType(Field field, Type srcType) {
// 获取字段的类型
Type fieldType = field.getGenericType();
// 获取声明字段的类
Class<?> declaringClass = field.getDeclaringClass();
// 执行解析操作
return resolveType(fieldType, srcType, declaringClass);
}
其中参数srcType指的是用于获取泛型实际类型的类/实际运行时的类/传参进来的类型所在的类,这是我看了很多博客后的总结。。反正也算理解那个意思了吧。
然后咱来到resolveType:
/**
* 将指定类型中的泛型定义转换为运行时的实际类型定义
*
* @param type 可能包含泛型定义的类型
* @param srcType 运行期间该类型所属的实例对象
* @param declaringClass 声明了type定义的类
* @return 指定类型处理完泛型定义后的类型
*/
private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
if (type instanceof TypeVariable) {
// 解析类型参数,比如: 泛型参数表示具体的某一独立的类型
return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
} else if (type instanceof ParameterizedType) {
// 解析参数化的泛型,比如:List list;
return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
} else if (type instanceof GenericArrayType) {
// 解析泛型数组,比如: List[] listArray;
return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
} else {
// 普通类型(Class)直接返回
return type;
}
}
resolveType的思路就是根据传参的type来确定接下来通过哪个方法来进行类型解析。
我们进入第一个方法:resolveTypeVar,这个方法是用来解析TypeVariable的,也就是泛型,具体实现如下:
/**
* 解析指定泛型变量的类型
*
* @param typeVar 泛型变量
* @param srcType 用于获取泛型变量实际类型的类
* @param declaringClass 实际声明该类型的类的类型
*/
private static Type resolveTypeVar(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass) {
Type result = null;
Class<?> clazz = null;
// step1: 处理srcType,移除泛型定义,获取对应的Class类型
if (srcType instanceof Class) {
clazz = (Class<?>) srcType;
} else if (srcType instanceof ParameterizedType) {
// 泛型参数取声明泛型的类型
ParameterizedType parameterizedType = (ParameterizedType) srcType;
clazz = (Class<?>) parameterizedType.getRawType();
} else {
// 理论上讲不会出现其他的类型场景
throw new IllegalArgumentException("The 2nd arg must be Class or ParameterizedType, but was: " + srcType.getClass());
}
// step2: 获取泛型定义的实际类型
// case1: 当前类就是声明了泛型的类
if (clazz == declaringClass) {
// 当前类就是声明了泛型的类,则泛型一定未被指定具体类型,获取泛型变量类型上限
Type[] bounds = typeVar.getBounds();
if (bounds.length > 0) {
return bounds[0];
}
// 没有指定泛型变量上限,那就是Object。
return Object.class;
}
// case2: 尝试从父类中获取泛型变量的实际类型
// 运行期间泛型所属的对象和声明泛型定义的不是同一个
// 获取其直接父类类型,尝试从父类中找到泛型定义
Type superclass = clazz.getGenericSuperclass();
// 递归处理父类,直到找到该泛型对应的实际类型,或者null值。
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superclass);
if (result != null) {
return result;
}
// case3: 无法通过父类获取泛型变量的实际类型,则通过接口定义获取泛型变量对应的实际类型
// 获取类实现的所有接口,尝试从接口中获取泛型变量的定义
Type[] superInterfaces = clazz.getGenericInterfaces();
for (Type superInterface : superInterfaces) {
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superInterface);
if (result != null) {
return result;
}
}
// 在接口中也未找到泛型变量的实际类型,返回Object类型。
return Object.class;
}
这个方法具体实现注释里面太明白了,我这里理下思路:
那么上面第4步中出现的scanSuperTypes咱也得分析一下:
private static Type scanSuperTypes(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass, Class<?> clazz, Type superclass) {
Type result = null;
/*
* 判断处理的父类superclass是否为参数化类型,如果不是则代表declaringClass和superclass的基本Class
* 类型不是同一个类。
*/
if (superclass instanceof ParameterizedType) {
//如果为ParameterizedType,则获取它基本类型
ParameterizedType parentAsType = (ParameterizedType) superclass;
Class<?> parentAsClass = (Class<?>) parentAsType.getRawType();
if (declaringClass == parentAsClass) {
//如果declaringClass和parentAsClass表示同一类型,则通过typeVar在declaringClass的泛型形参的index获取其在supperClass中定义的类型实参
Type[] typeArgs = parentAsType.getActualTypeArguments();
TypeVariable<?>[] declaredTypeVars = declaringClass.getTypeParameters();
for (int i = 0; i < declaredTypeVars.length; i++) {
//循环判断当前处理的类型是否属于所属的类型描述符中的变量
if (declaredTypeVars[i] == typeVar) {
/*
*如果supperClass中定义的类型形参还是类型变量则取srcType中的类型形参的定义
* 如果srcType中的类型形参还是类型变量则不处理。
*/
if (typeArgs[i] instanceof TypeVariable) {
//其子类中的所有泛型描述符
TypeVariable<?>[] typeParams = clazz.getTypeParameters();
for (int j = 0; j < typeParams.length; j++) {
if (typeParams[j] == typeArgs[i]) {
//判断是否为ParameterizedType,则去实际代表的类型
if (srcType instanceof ParameterizedType) {
result = ((ParameterizedType) srcType).getActualTypeArguments()[j];
}
break;
}
}
} else {
//如果不是TypeVariable,直接取对应的类型
result = typeArgs[i];
}
}
}
} else if (declaringClass.isAssignableFrom(parentAsClass)) {
//通过判断superclass是否是declaringClass的子类(由于java类可以实现多个接口),进行递归解析
result = resolveTypeVar(typeVar, parentAsType, declaringClass);
}
} else if (superclass instanceof Class) {
//如果superclass为Class类型,通过判断superclass是否是declaringClass的子类(由于java类可以实现多个接口),进行递归解析
if (declaringClass.isAssignableFrom((Class<?>) superclass)) {
result = resolveTypeVar(typeVar, superclass, declaringClass);
}
}
return result;
}
同样的,注释写的太明白了,我自己理一遍思路:
到这里resolveTypeVar就结束了,然后是resolveParameterizedType:
private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class<?> declaringClass) {
//获取泛型的基本类型
Class<?> rawType = (Class<?>) parameterizedType.getRawType();
//获取泛型中的类型实参
Type[] typeArgs = parameterizedType.getActualTypeArguments();
//递归处理其类型实参
Type[] args = new Type[typeArgs.length];
for (int i = 0; i < typeArgs.length; i++) {
//判断对应参数的类型,分别进行递归处理
if (typeArgs[i] instanceof TypeVariable) {
//解析TypeVariable类型
args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof ParameterizedType) {
//解析ParameterizedType类型
args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof WildcardType) {
//是解析WildcardType类型(其类型实参是通配符表达式)
args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);
} else {
//普通Class类型,直接返回
args[i] = typeArgs[i];
}
}
//返回自定以类型
return new ParameterizedTypeImpl(rawType, null, args);
}
resolveGenericArrayType和上面这个差不多,我也不再写了。。
到这里都还是昏昏的,过程大概有了个了解,但是和实列还是对不上,等后边学习到使用这个工具类部分的时候再理解吧。
个人博客:qlumen.cn