2.4.6.解析泛型实际类型的工具类 TypeParameterResolver
TypeParameterResolver
是mybaits中定义的一个用于解析泛型实际类型的工具类。
在java中定义了一个名为Type
的接口,他是java编程语言中所有类型的公共接口,这里的类型包括了原始类型、参数化类型、数组类型、类型变量和基本类型。
简单了解一下Type
相关的接口
我们可以通过下面这个类定义简单的了解一下不同类型的区别:
/**
* 一个简单的泛型对象的定义
* {@link #getPlanetSize()} 获取星球的大小,返回值为double类型,是一个原始数据类型,对应着{@link Class}。
* {@link #membersCount()} 获取星球成员的数量,返回值为BigDecimal类型,属于java类型中的复杂类,对应着{@link Class}。
* {@link #leader()}获取外星人首领,返回值为泛型变量定义E,是一个可变的类型定义,对应着{@link java.lang.reflect.TypeVariable}
* {@link #getPlanet(Object)}获取星球本身,返回值是一个定义了泛型变量的{@link Planet<E>}类型定义本身(包含E定义),
* 是一个参数化类型,因为在这个定义中包含了他的泛型参数定义,对应着{@link java.lang.reflect.ParameterizedType}。
* {@link #members()} 获取外星人的成员集合,返回值是一个元素类型为泛型变量{@link E}的泛型数组,他的类型取决于元素的类型,它对应着{@link java.lang.reflect.GenericArrayType}。
* {@link #neighborhoods()} 获取该星球附近的星球,返回值是一个`List<? extends Planet>`,该返回值本身是一个参数化类型,但是他的泛型定义`? extends Planet`因为包含了通配符`?`,所以他的泛型参数类型`? extends Planet`是一个通配符形式的泛型类型,对应着{@link java.lang.reflect.WildcardType};
*
* @param <E> E是一个类型变量,他会根据实际需要改变类型
*/
abstract class Planet<E> {
/**
* 获取星球大小
* double: 原始类型
*/
public abstract double getPlanetSize();
/**
* 获取外星人成员的总数
* BigDecimal:基本类型
*/
public abstract BigDecimal membersCount();
/**
* 获取外星人首领
* E:类型变量
*/
public abstract E leader();
/**
* 获取星球本身
* Planet<E>:参数化类型
*/
public abstract Planet<E> getPlanet(E e);
/**
* 获取外星人的成员集合
* E[]:数组类型,泛型数组
*/
public abstract E[] members();
/**
* 获取该星球附近的星球
* <? extends Planet>:通配符泛型类型:
*/
public abstract List<? extends Planet> neighborhoods();
}
总览TypeParameterResolver对外提供的方法
在对Type
及其实现类有了一定的了解之后,我们再看TypeParameterResolver
类,该类对外暴露了三个静态方法:resolveFieldType
、resolveReturnType
、resolveParamTypes
。
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); }
resolveReturnType
方法用于获取处理完泛型后的方法返回值的实际类型:/** * 获取指定方法的返回类型,将泛型转换为实际类型 * * @param method 方法 * @param srcType 运行时方法所属对象类型 * @return 如果方法返回值在声明的时候有泛型定义,这些泛型会被解析会运行时的实际类型 */ public static Type resolveReturnType(Method method, Type srcType) { // 获取方法返回类型 Type returnType = method.getGenericReturnType(); // 获取声明该方法的对象的类型 Class<?> declaringClass = method.getDeclaringClass(); return resolveType(returnType, srcType, declaringClass); }
resolveParamTypes
方法用于获取处理完泛型后的方法入参类型集合:/** * 获取指定方法的所有入参的实际类型,将泛型转换为实际类型 * * @param method 方法 * @param srcType 通过反射获取该方法的类的类型 * @return 如果方法入参在声明的时候有泛型定义,这些泛型会被解析会运行时的实际类型 */ public static Type[] resolveParamTypes(Method method, Type srcType) { // 获取所有方法入参 Type[] paramTypes = method.getGenericParameterTypes(); // 声明该方法的类 Class<?> declaringClass = method.getDeclaringClass(); Type[] result = new Type[paramTypes.length]; // 依次处理 for (int i = 0; i < paramTypes.length; i++) { result[i] = resolveType(paramTypes[i], srcType, declaringClass); } return result; }
真正处理泛型工作的是resolveType
方法
这三个方法在实现上,都是先获取可能包含了泛型定义的类型定义,之后获取负责声明该类型的类定义,然后将具体的处理泛型的工作交给了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<T> list;
return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
} else if (type instanceof GenericArrayType) {
// 解析泛型数组,比如: List<N>[] listArray;
return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
} else {
// 普通类型(Class)直接返回
return type;
}
}
resolveType
方法入参说明
resolveType
方法有三个入参type
,srcType
,declaringClass
,其中:
type
表示需要被处理的可能包含泛型定义的类型,srcType
表示运行期间type
所属的实例对象的类型,declaringClass
表示声明了type
定义的类。
举例说明:
@Test
@SneakyThrows
public void assertType() {
// 获取getEntities方法
Method getEntitiesMethod = Sub.class.getMethod("getEntities");
assert Super.class.equals(getEntitiesMethod.getDeclaringClass());
// 获取方法返回值的泛型定义
Type returnType = getEntitiesMethod.getGenericReturnType();
assert returnType instanceof ParameterizedType;
// 获取父接口的定义
Type superType = Sub.class.getGenericInterfaces()[0];
assert superType instanceof ParameterizedType;
assert ((ParameterizedType) superType).getActualTypeArguments()[0].equals(String.class);
}
private interface Super<E> {
List<E> getEntities();
}
private interface Sub extends Super<String> {
}
我们定义了一个具有泛型定义的Super
接口,并在其中定义了一个名为getEntities
的方法,该方法的返回值类型是List
,List
中存放的元素类型取决于Super
的泛型定义, 之后定义一个Sub
接口继承Super
接口,同时在Sub
中将在Super
中定义的泛型类型精确为String
。
在这个示例中getEntities
方法的返回值类型List<E>
包含了泛型定义,当我们使用resolveType
方法来尝试解析E
的实际类型时,List<E>
就是resolveType
方法的type
参数——一个需要被处理的可能包含泛型定义的类型定义。
而用于获取方法对象getEntities
的接口定义Sub
,就会作为参数srcType
传递给resolveType
方法。
最后,实际声明了泛型E
的接口Super
则会作为参数declaringClass
传递给resolveType
方法.
resolveType
方法的解析泛型的逻辑
在resolveType
方法中,按照类型的不同,解析泛型的操作对应着四种不同的处理方式:
- 解析泛型变量使用
resolveTypeVar
方法 - 解析参数化泛型使用
resolveParameterizedType
方法 - 解析泛型数组使用
resolveGenericArrayType
方法 - 解析普通类型则直接返回类型本身
除了这四种处理方式之外,还有一种特殊的、用于处理通配符性质的泛型定义的方法:resolveWildcardType
.
通配符性质的泛型定义(
WildcardType
):List<? extends N> list
。
所以对于泛型的解析操作实际上有五种,不过如果去除对普通类型的处理,实际上还是只有四种,现在我们依次看这四种不同类型的解析实现:
解析泛型变量的resolveTypeVar
方法
/**
* 解析指定泛型变量的类型
*
* @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;
}
在resolveTypeVar
方法中,首先会将srcType
解析成普通的Class
类型,如果srcType
原本就是一个普通的Class
,那就不需要处理, 如果srcType
是一个参数化泛型定义,就移除掉泛型定义部分,返回类型定义本身,比如把Super<E>
转换为Super
,移除其中的泛型定义E
.
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());
}
在获取到srcType
对应的Class
类型之后,就可以获取type
泛型定义了,获取type
泛型定义的逻辑也比较简单:
- 如果
srcType
就是声明了泛型定义的类,那么尝试取出泛型变量的类型上限,如果没有定义泛型类型上限,则返回Object.class
。 - 如果
srcType
不是声明泛型定义的类,那就委托给scanSuperTypes
方法,尝试从父类中找到泛型定义对应的实际类型。 - 如果从父类中也找不到泛型定义对应的实际类型,还是委托给
scanSuperTypes
方法,不过这次是尝试从srcType
实现的所有接口定义中找。 - 如果在接口中也找不到,那就返回
Object.class
。
下面是具体实现:
直接取值:如果
srcType
就是声明了泛型定义的类,那么尝试取出泛型变量的类型上限,如果没有定义泛型类型上限,则返回Object.class
。
// step2: 获取泛型定义的实际类型
// case1: 当前类就是声明了泛型的类
if (clazz == declaringClass) {
// 当前类就是声明了泛型的类,则泛型一定未被指定具体类型,获取泛型变量类型上限
Type[] bounds = typeVar.getBounds();
if (bounds.length > 0) {
return bounds[0];
}
// 没有指定泛型变量上限,那就是Object。
return Object.class;
}
通过父类获取:如果
srcType
不是声明泛型定义的类,那就委托给scanSuperTypes
方法,尝试从父类中找到泛型定义对应的实际类型,
// case2: 尝试从父类中获取泛型变量的实际类型
// 运行期间泛型所属的对象和声明泛型定义的不是同一个
// 获取其直接父类类型,尝试从父类中找到泛型定义
Type superclass = clazz.getGenericSuperclass();
// 递归处理父类,直到找到该泛型对应的实际类型,或者null值。
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superclass);
if (result != null) {
return result;
}
通过接口获取:如果从父类中还找不到泛型定义对应的实际类型,还是委托给
scanSuperTypes
方法,不过这次是尝试从srcType
实现的所有接口定义中找,如果在接口中也找不到,那就返回Object.class
。
// 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;
上文中调用的scanSuperTypes
方法的主要作用就是尝试从指定的类及其父类/接口中找到指定泛型的实际类型定义:
/**
* @param typeVar 泛型变量的类型
* @param srcType 泛型变量所属对象的类
* @param declaringClass 声明泛型变量的类
* @param clazz 泛型变量所属对象处理泛型后的类型
* @param superclass srcType直接父类或者接口
*/
private static Type scanSuperTypes(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass, Class<?> clazz, Type superclass) {
// 针对父类的类型定义有三种处理方案
// 1.参数化泛型
// 2.普通类同时是声明了泛型的类的实现
// 3.普通类但不是声明了泛型实现的类的实现
if (superclass instanceof ParameterizedType) {
// case1:参数化泛型定义类
ParameterizedType parentAsType = (ParameterizedType) superclass;
// 获取父类除去泛型定义之后的类型
Class<?> parentAsClass = (Class<?>) parentAsType.getRawType();
// 获取父类中的泛型定义
TypeVariable<?>[] parentTypeVars = parentAsClass.getTypeParameters();
// 泛型变量所属对象的类也是一个泛型对象
if (srcType instanceof ParameterizedType) {
// 合并子类和父类的泛型定义比如: Super<A,B>{},Sub extend Super<String,Integer>.
parentAsType = translateParentTypeVars((ParameterizedType) srcType, clazz, parentAsType);
}
if (declaringClass == parentAsClass) {
// 父类就是声明了泛型变量的类
for (int i = 0; i < parentTypeVars.length; i++) {
// 找到了typeVar对应的实际类型定义
if (typeVar == parentTypeVars[i]) {
// 返回泛型的实际类型
return parentAsType.getActualTypeArguments()[i];
}
}
}
if (declaringClass.isAssignableFrom(parentAsClass)) {
// 父类是声明了泛型类的子类,继续递归查找
return resolveTypeVar(typeVar, parentAsType, declaringClass);
}
} else if (superclass instanceof Class && declaringClass.isAssignableFrom((Class<?>) superclass)) {
// case2: 父类是一个普通的类,同时父类是泛型变量所属定义类的子实现
// 递归
return resolveTypeVar(typeVar, superclass, declaringClass);
}
// 父类不是泛型类,同时父类不是泛型变量声明类的实现
return null;
}
在scanSuperTypes
方法中,针对传入的superclass
类型的不同,有三种不同的处理策略:
- 如果
superclass
是参数化类型的话(ParameterizedType
),那就尝试解析superclass
中的泛型定义,用来获取指定泛型变量的实际类型。 - 如果
superclass
是一个普通的Class
并且是声明了泛型变量的declaringClass
的子类,那就把superclass
作为srcType
参数传给resolveTypeVar
方法,递归处理。 - 如果
superclass
是一个普通的Class
而且和声明了泛型变量的declaringClass
没有任何关系,那就返回null
。
这三种处理策略中,第一种处理稍微复杂一些,其余两种处理策略相对来说都比较简单,没有太过复杂的业务。
所以我们只需要看一下当superclass
是一个参数化类型时的处理逻辑即可:
if (superclass instanceof ParameterizedType) {
// case1:参数化泛型定义类
ParameterizedType parentAsType = (ParameterizedType) superclass;
// 获取父类除去泛型定义之后的类型
Class<?> parentAsClass = (Class<?>) parentAsType.getRawType();
// 获取父类中的泛型定义
TypeVariable<?>[] parentTypeVars = parentAsClass.getTypeParameters();
// 泛型变量所属对象的类也是一个泛型对象
if (srcType instanceof ParameterizedType) {
// 合并子类和父类的泛型定义比如: Super<A,B>{},Sub extend Super<String,Integer>.
parentAsType = translateParentTypeVars((ParameterizedType) srcType, clazz, parentAsType);
}
if (declaringClass == parentAsClass) {
// 父类就是声明了泛型变量的类
for (int i = 0; i < parentTypeVars.length; i++) {
// 找到了typeVar对应的实际类型定义
if (typeVar == parentTypeVars[i]) {
// 返回泛型的实际类型
return parentAsType.getActualTypeArguments()[i];
}
}
}
if (declaringClass.isAssignableFrom(parentAsClass)) {
// 父类是声明了泛型类的子类,继续递归查找
return resolveTypeVar(typeVar, parentAsType, declaringClass);
}
}
将superclass
强转成ParameterizedType
类型并赋值给parentAsType
变量,之后通过parentAsType
变量分别获取表示superclass
的基本类型和泛型定义。
如果传入的srcType
也是一个泛型变量的话,接下来就调用translateParentTypeVars
方法将srcType
和superclass
中的泛型实参合并起来,得到一个新的parentAsType
。
比如:
interface Super<L, M, N> {}
interface Sub<E, F> extends Super<E, F, String> {}
Sub
作为srcType
参数,Super
作为parentAsType
参数,经过translateParentTypeVars
方法的处理之后,parentAsType
的值就会由Super<L, M, N>
变成Super<E, F, String>
,注意这里的L/M
也变成了E/F
。
完成合并子类和父类的泛型定义的操作之后,根据当前处理的父类parentAsClass
和声明了泛型定义的类declaringClass
的关系,来完成实际的泛型类型的获取工作:
- 如果当前父类就是声明了泛型定义的类,那就直接从处理后的泛型数组中获取泛型对应的实际类型,
- 如果当前父类是声明了泛型的类的子类,那就继续把父类作为
srcType
属性传给resolveTypeVar
方法,递归完成解析操作。 - 如果当前父类和声明了泛型的类型没有任何关系,不做任何处理,也就意味着返回
null
值。
前面已经说过在resolveTypeVar
方法中,如果使用指定类的父类作为参数调用scanSuperTypes
方法时返回了null
,那么就会尝试用指定类的接口作为参数继续调用scanSuperTypes
方法,如果用接口做参数时还是返回null
,那就返回Object.class
。
合并子类和父类泛型定义的方法translateParentTypeVars
的实现也比较简单,他在合并子类和父类中的泛型定义时,会尽可能的用在子类中定义的实际参数类型取代父类中的泛型参数定义:
private static ParameterizedType translateParentTypeVars(ParameterizedType srcType, Class<?> srcClass, ParameterizedType parentType) {
// 获取父类定义的泛型变量的实际类型数组
Type[] parentTypeArgs = parentType.getActualTypeArguments();
// 获取子类定义的泛型变量的实际类型数组
Type[] srcTypeArgs = srcType.getActualTypeArguments();
// 获取子类中的泛型变量定义
TypeVariable<?>[] srcTypeVars = srcClass.getTypeParameters();
// 父类泛型实参数组
Type[] newParentArgs = new Type[parentTypeArgs.length];
boolean noChange = true;
for (int i = 0; i < parentTypeArgs.length; i++) {
if (parentTypeArgs[i] instanceof TypeVariable) {
// 泛型变量
for (int j = 0; j < srcTypeVars.length; j++) {
if (srcTypeVars[j] == parentTypeArgs[i]) {
// 子类泛型定义和父类泛型定义一致,则子类中泛型变量的实参对应着父类泛型变量的实参
noChange = false;
// 从子类中取出泛型变量的实际类型
newParentArgs[i] = srcTypeArgs[j];
}
}
} else {
// 父类中指定了泛型对应的实际类型
newParentArgs[i] = parentTypeArgs[i];
}
}
// 合并子类和父类的泛型定义
return noChange ? parentType
: new ParameterizedTypeImpl((Class<?>) parentType.getRawType(), null, newParentArgs);
}
比如前面提到过的:
interface Super<L, M, N> {}
interface Sub<E, F> extends Super<E, F, String> {}
经过translateParentTypeVars
方法的处理之后,parentAsType
就会由Super<L, M, N>
变成Super<E, F, String>
,其中L/M
变成了E/F
,就是因为: 只要子类中泛型定义和父类中定义不一致,就会取代父类中的泛型定义,哪怕在子类中其实是使用一个新的泛型取代了父类中旧的泛型定义。
for (int i = 0; i < parentTypeArgs.length; i++) {
if (parentTypeArgs[i] instanceof TypeVariable) {
// 泛型变量
for (int j = 0; j < srcTypeVars.length; j++) {
if (srcTypeVars[j] == parentTypeArgs[i]) {
// 子类泛型定义和父类泛型定义一致,则子类中泛型变量的实参对应着父类泛型变量的实参
noChange = false;
// 从子类中取出泛型变量的实际类型
newParentArgs[i] = srcTypeArgs[j];
}
}
} else {
// 父类中指定了泛型对应的实际类型
newParentArgs[i] = parentTypeArgs[i];
}
}
ok,到这里,用于解析泛型变量的resolveTypeVar
方法的整个逻辑就梳理完成了,接下来继续看看用来解析参数化泛型的resolveParameterizedType
方法。
解析参数化泛型使用resolveParameterizedType
方法
/**
* 解析参数化泛型的实际类型
*
* @param parameterizedType 泛型类型
* @param srcType 运行期间该类型所属的实例对象
* @param declaringClass 声明了parameterizedType定义的类
*/
private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class<?> declaringClass) {
// 获取参数化泛型中的原始类比如:List<E>中的E
Class<?> rawType = (Class<?>) parameterizedType.getRawType();
// 获取实际泛型实参列表,比如List<String>会得到[String]。
Type[] typeArgs = parameterizedType.getActualTypeArguments();
// 声明参数集合
Type[] args = new Type[typeArgs.length];
// 依次处理泛型参数的实际类型,比如Map<K,V>,依次获取K和V的实际类型
for (int i = 0; i < typeArgs.length; i++) {
if (typeArgs[i] instanceof TypeVariable) {
// 解析泛型变量使用resolveTypeVar方法:比如:Class<A extends B>获取A和B的类型
args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof ParameterizedType) {
// 解析泛型参数使用resolveParameterizedType方法,比如:List<T> list;
args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof WildcardType) {
// 解析通配符表达式形式的泛型,比如:List<? extends N> list;
args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);
} else {
// 普通的Class类型直接返回
args[i] = typeArgs[i];
}
}
// 重新包装成ParameterizedType返回
return new ParameterizedTypeImpl(rawType, null, args);
}
在resolveParameterizedType
方法的实现中,大部分工作的完成都是依赖于其他方法来完成的:
- 解析泛型变量委托给
resolveTypeVar
方法if (typeArgs[i] instanceof TypeVariable) { // 解析泛型变量使用resolveTypeVar方法:比如:Class<A extends B>获取A和B的类型 args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass); }
- 解析参数化泛型委托给resolveParameterizedType方法本身,递归调用完成解析操作
else if (typeArgs[i] instanceof ParameterizedType) { // 解析泛型参数使用resolveParameterizedType方法,比如:List<T> list; args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass); }
- 解析通配符表达式形式的泛型委托给了方法
resolveWildcardType
,该方法后面会给出else if (typeArgs[i] instanceof WildcardType) { // 解析通配符表达式形式的泛型,比如:List<? extends N> list; args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass); }
- 普通类型的Class则直接返回
else { // 普通的Class类型直接返回 args[i] = typeArgs[i]; }
解析泛型数组使用resolveGenericArrayType
方法
resolveGenericArrayType
方法比较简单,在获取泛型数组中的元素的实际类型之后,将其转换为对应的数组类型返回即可。
private static Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType, Class<?> declaringClass) {
// 获取数组泛型中元素的泛型类型,比如: T[] testArray中T的类型
Type componentType = genericArrayType.getGenericComponentType();
// 解析元素的泛型类型
Type resolvedComponentType = null;
if (componentType instanceof TypeVariable) {
// 解析泛型变量:Class<A extends B>
resolvedComponentType = resolveTypeVar((TypeVariable<?>) componentType, srcType, declaringClass);
} else if (componentType instanceof GenericArrayType) {
// 递归解析泛型数组:List<N>[] listArray;
resolvedComponentType = resolveGenericArrayType((GenericArrayType) componentType, srcType, declaringClass);
} else if (componentType instanceof ParameterizedType) {
// 解析参数化泛型:List<T> list
resolvedComponentType = resolveParameterizedType((ParameterizedType) componentType, srcType, declaringClass);
}
// 将解析出的泛型类型转换为数组类型
if (resolvedComponentType instanceof Class) {
return Array.newInstance((Class<?>) resolvedComponentType, 0).getClass();
} else {
// 解析出来泛型的实际类型还是一个泛型定义
return new GenericArrayTypeImpl(resolvedComponentType);
}
}
获取泛型数组中元素的类型的具体操作也是委托给其他方法来完成的:
- 解析泛型变量委托给
resolveTypeVar
方法 - 解析泛型数组委托给
resolveGenericArrayType
本身,递归调用 - 解析参数化泛型委托给
resolveParameterizedType
方法。
解析通配符性质的泛型定义使用resolveWildcardType
方法
通配符性质的参数化泛型WildcardType
可以说是参数化泛型的一种特殊实现,他可以为泛型参数定义
private static Type resolveWildcardType(WildcardType wildcardType, Type srcType, Class<?> declaringClass) {
// 获取通配符泛型对应的类型下限
Type[] lowerBounds = resolveWildcardTypeBounds(wildcardType.getLowerBounds(), srcType, declaringClass);
// 获取通配符泛型对应的类型上限
Type[] upperBounds = resolveWildcardTypeBounds(wildcardType.getUpperBounds(), srcType, declaringClass);
// 包装通配符泛型实现
return new WildcardTypeImpl(lowerBounds, upperBounds);
}
具体完成获取通配符泛型实际类型工作的是方法resolveWildcardTypeBounds
:
/**
* @param bounds 类型边界
* @param srcType 泛型变量所属类
* @param declaringClass 泛型变量声明类
*/
private static Type[] resolveWildcardTypeBounds(Type[] bounds, Type srcType, Class<?> declaringClass) {
Type[] result = new Type[bounds.length];
// 依次处理泛型边界中的每个具体的泛型定义
for (int i = 0; i < bounds.length; i++) {
if (bounds[i] instanceof TypeVariable) {
// 处理泛型变量
result[i] = resolveTypeVar((TypeVariable<?>) bounds[i], srcType, declaringClass);
} else if (bounds[i] instanceof ParameterizedType) {
// 处理参数化泛型
result[i] = resolveParameterizedType((ParameterizedType) bounds[i], srcType, declaringClass);
} else if (bounds[i] instanceof WildcardType) {
// 递归处理通配符泛型,我脑海里暂时想不出来什么时候会执行这一行代码
// 如果有人知道的话,麻烦在您方便的情况下,告知我,谢谢了~
// 我的邮箱: jpanda@aliyun.com
result[i] = resolveWildcardType((WildcardType) bounds[i], srcType, declaringClass);
} else {
// 普通Class
result[i] = bounds[i];
}
}
return result;
}
整个获取通配符泛型实际类型的操作也比较简单,基本上都是委托给其他方法来完成的,里面唯一值得注意的是else if (bounds[i] instanceof WildcardType)
这一块代码,我很难理解在正常的途径下如何触发这块代码。
如果您知道的话,可以通过邮件jpanda@aliyun.com来告知我,十分感激。