基本使用
TypeParameterResolver
能做什么?
- 获取字段的类型,如
String name;
中的String - 获取方法返回值类型,如
Double simpleSelect();
中的Double - 获取方法入参类型,如
void simpleSelectVoid(Integer param);
中的Integer
基本使用例子
import static org.junit.Assert.assertEquals;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import org.junit.Test;
public class MyTypeParameterResolverTest {
static class Person {
private String name;
String test(Integer n) {
return name;
}
}
@Test
public void testReturn_String() throws Exception {
Class<?> clazz = Person.class;
Method method = clazz.getDeclaredMethod("test", Integer.class);
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertEquals(String.class, result);
}
@Test
public void testParam_Integer() throws Exception {
Class<?> clazz = Person.class;
Method method = clazz.getDeclaredMethod("test", Integer.class);
Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
assertEquals(Integer.class, result[0]);
}
@Test
public void testField_String() throws Exception {
Class<?> clazz = Person.class;
Field field = clazz.getDeclaredField("name");
Type result = TypeParameterResolver.resolveFieldType(field, clazz);
assertEquals(String.class, result);
}
}
获取复杂类型参数
包括java type
- ParameterizedType
- TypeVariable
- GenericArrayType
- WildcardType
使用如下
public class TypeParameterResolverTest {
@Test
public void testReturn_Lv0SimpleClass() throws Exception {
// Double simpleSelect();
Class<?> clazz = Level0Mapper.class;
Method method = clazz.getMethod("simpleSelect");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertEquals(Double.class, result);
}
@Test
public void testReturn_SimpleVoid() throws Exception {
// void simpleSelectVoid(Integer param);
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("simpleSelectVoid", Integer.class);
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertEquals(void.class, result);
}
@Test
public void testReturn_SimplePrimitive() throws Exception {
// double simpleSelectPrimitive(int param);
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("simpleSelectPrimitive", int.class);
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertEquals(double.class, result);
}
@Test
public void testReturn_SimpleClass() throws Exception {
// Double simpleSelect();
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("simpleSelect");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertEquals(Double.class, result);
}
@Test
public void testReturn_SimpleList() throws Exception {
// List<Double> simpleSelectList();
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("simpleSelectList");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof ParameterizedType);
ParameterizedType paramType = (ParameterizedType) result;
assertEquals(List.class, paramType.getRawType());
assertEquals(1, paramType.getActualTypeArguments().length);
assertEquals(Double.class, paramType.getActualTypeArguments()[0]);
}
@Test
public void testReturn_SimpleMap() throws Exception {
// Map<Integer, Double> simpleSelectMap();
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("simpleSelectMap");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof ParameterizedType);
ParameterizedType paramType = (ParameterizedType) result;
assertEquals(Map.class, paramType.getRawType());
assertEquals(2, paramType.getActualTypeArguments().length);
assertEquals(Integer.class, paramType.getActualTypeArguments()[0]);
assertEquals(Double.class, paramType.getActualTypeArguments()[1]);
}
@Test
public void testReturn_SimpleWildcard() throws Exception {
// List<? extends String> simpleSelectWildcard();
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("simpleSelectWildcard");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof ParameterizedType);
ParameterizedType paramType = (ParameterizedType) result;
assertEquals(List.class, paramType.getRawType());
assertEquals(1, paramType.getActualTypeArguments().length);
assertTrue(paramType.getActualTypeArguments()[0] instanceof WildcardType);
WildcardType wildcard = (WildcardType) paramType.getActualTypeArguments()[0];
assertEquals(String.class, wildcard.getUpperBounds()[0]);
}
@Test
public void testReturn_SimpleArray() throws Exception {
// String[] simpleSelectArray();
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("simpleSelectArray");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof Class);
Class<?> resultClass = (Class<?>) result;
assertTrue(resultClass.isArray());
assertEquals(String.class, resultClass.getComponentType());
}
@Test
public void testReturn_SimpleArrayOfArray() throws Exception {
// String[][] simpleSelectArrayOfArray();
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("simpleSelectArrayOfArray");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof Class);
Class<?> resultClass = (Class<?>) result;
assertTrue(resultClass.isArray());
assertTrue(resultClass.getComponentType().isArray());
assertEquals(String.class, resultClass.getComponentType().getComponentType());
}
@Test
public void testReturn_SimpleTypeVar() throws Exception {
// <K extends Calculator<?>> K simpleSelectTypeVar();
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("simpleSelectTypeVar");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertEquals(Object.class, result);
}
@Test
public void testReturn_Lv1Class() throws Exception {
// N select(N param);
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("select", Object.class);
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertEquals(String.class, result);
}
@Test
public void testReturn_Lv2CustomClass() throws Exception {
// Calculator<N> selectCalculator(Calculator<N> param);
Class<?> clazz = Level2Mapper.class;
Method method = clazz.getMethod("selectCalculator", Calculator.class);
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof ParameterizedType);
ParameterizedType paramType = (ParameterizedType) result;
assertEquals(Calculator.class, paramType.getRawType());
assertEquals(1, paramType.getActualTypeArguments().length);
assertEquals(String.class, paramType.getActualTypeArguments()[0]);
}
@Test
public void testReturn_Lv2CustomClassList() throws Exception {
// List<Calculator<L>> selectCalculatorList();
Class<?> clazz = Level2Mapper.class;
Method method = clazz.getMethod("selectCalculatorList");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof ParameterizedType);
ParameterizedType paramTypeOuter = (ParameterizedType) result;
assertEquals(List.class, paramTypeOuter.getRawType());
assertEquals(1, paramTypeOuter.getActualTypeArguments().length);
ParameterizedType paramTypeInner = (ParameterizedType) paramTypeOuter.getActualTypeArguments()[0];
assertEquals(Calculator.class, paramTypeInner.getRawType());
assertEquals(Date.class, paramTypeInner.getActualTypeArguments()[0]);
}
@Test
public void testReturn_Lv0InnerClass() throws Exception {
// N select(N param);
Class<?> clazz = Level0InnerMapper.class;
Method method = clazz.getMethod("select", Object.class);
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertEquals(Float.class, result);
}
@Test
public void testReturn_Lv2Class() throws Exception {
// N select(N param);
Class<?> clazz = Level2Mapper.class;
Method method = clazz.getMethod("select", Object.class);
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertEquals(String.class, result);
}
@Test
public void testReturn_Lv1List() throws Exception {
// List<N> selectList(M param1, N param2);
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("selectList", Object.class, Object.class);
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof ParameterizedType);
ParameterizedType type = (ParameterizedType) result;
assertEquals(List.class, type.getRawType());
assertEquals(1, type.getActualTypeArguments().length);
assertEquals(String.class, type.getActualTypeArguments()[0]);
}
@Test
public void testReturn_Lv1Array() throws Exception {
// N[] selectArray(List<N>[] param);
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("selectArray", List[].class);
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof Class);
Class<?> resultClass = (Class<?>) result;
assertTrue(resultClass.isArray());
assertEquals(String.class, resultClass.getComponentType());
}
@Test
public void testReturn_Lv2ArrayOfArray() throws Exception {
// N[][] selectArrayOfArray();
Class<?> clazz = Level2Mapper.class;
Method method = clazz.getMethod("selectArrayOfArray");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof Class);
Class<?> resultClass = (Class<?>) result;
assertTrue(result instanceof Class);
assertTrue(resultClass.isArray());
assertTrue(resultClass.getComponentType().isArray());
assertEquals(String.class, resultClass.getComponentType().getComponentType());
}
@Test
public void testReturn_Lv2ArrayOfList() throws Exception {
// List<N>[] selectArrayOfList();
Class<?> clazz = Level2Mapper.class;
Method method = clazz.getMethod("selectArrayOfList");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof GenericArrayType);
GenericArrayType genericArrayType = (GenericArrayType) result;
assertTrue(genericArrayType.getGenericComponentType() instanceof ParameterizedType);
ParameterizedType paramType = (ParameterizedType) genericArrayType.getGenericComponentType();
assertEquals(List.class, paramType.getRawType());
assertEquals(String.class, paramType.getActualTypeArguments()[0]);
}
@Test
public void testReturn_Lv2WildcardList() throws Exception {
// List<? extends N> selectWildcardList();
Class<?> clazz = Level2Mapper.class;
Method method = clazz.getMethod("selectWildcardList");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof ParameterizedType);
ParameterizedType type = (ParameterizedType) result;
assertEquals(List.class, type.getRawType());
assertEquals(1, type.getActualTypeArguments().length);
assertTrue(type.getActualTypeArguments()[0] instanceof WildcardType);
WildcardType wildcard = (WildcardType) type.getActualTypeArguments()[0];
assertEquals(0, wildcard.getLowerBounds().length);
assertEquals(1, wildcard.getUpperBounds().length);
assertEquals(String.class, wildcard.getUpperBounds()[0]);
}
@Test
public void testReturn_LV2Map() throws Exception {
// Map<N, M> selectMap();
Class<?> clazz = Level2Mapper.class;
Method method = clazz.getMethod("selectMap");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof ParameterizedType);
ParameterizedType paramType = (ParameterizedType) result;
assertEquals(Map.class, paramType.getRawType());
assertEquals(2, paramType.getActualTypeArguments().length);
assertEquals(String.class, paramType.getActualTypeArguments()[0]);
assertEquals(Integer.class, paramType.getActualTypeArguments()[1]);
}
@Test
public void testReturn_Subclass() throws Exception {
Class<?> clazz = SubCalculator.class;
Method method = clazz.getMethod("getId");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertEquals(String.class, result);
}
@Test
public void testParam_Primitive() throws Exception {
// double simpleSelectPrimitive(int param);
Class<?> clazz = Level2Mapper.class;
Method method = clazz.getMethod("simpleSelectPrimitive", int.class);
Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
assertEquals(1, result.length);
assertEquals(int.class, result[0]);
}
@Test
public void testParam_Simple() throws Exception {
// void simpleSelectVoid(Integer param);
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("simpleSelectVoid", Integer.class);
Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
assertEquals(1, result.length);
assertEquals(Integer.class, result[0]);
}
@Test
public void testParam_Lv1Single() throws Exception {
// N select(N param);
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("select", Object.class);
Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
assertEquals(1, result.length);
assertEquals(String.class, result[0]);
}
@Test
public void testParam_Lv2Single() throws Exception {
// N select(N param);
Class<?> clazz = Level2Mapper.class;
Method method = clazz.getMethod("select", Object.class);
Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
assertEquals(1, result.length);
assertEquals(String.class, result[0]);
}
@Test
public void testParam_Lv2Multiple() throws Exception {
// List<N> selectList(M param1, N param2);
Class<?> clazz = Level2Mapper.class;
Method method = clazz.getMethod("selectList", Object.class, Object.class);
Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
assertEquals(2, result.length);
assertEquals(Integer.class, result[0]);
assertEquals(String.class, result[1]);
}
@Test
public void testParam_Lv2CustomClass() throws Exception {
// Calculator<N> selectCalculator(Calculator<N> param);
Class<?> clazz = Level2Mapper.class;
Method method = clazz.getMethod("selectCalculator", Calculator.class);
Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
assertEquals(1, result.length);
assertTrue(result[0] instanceof ParameterizedType);
ParameterizedType paramType = (ParameterizedType) result[0];
assertEquals(Calculator.class, paramType.getRawType());
assertEquals(1, paramType.getActualTypeArguments().length);
assertEquals(String.class, paramType.getActualTypeArguments()[0]);
}
@Test
public void testParam_Lv1Array() throws Exception {
// String[] simpleSelectArray();
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("selectArray", List[].class);
Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
assertTrue(result[0] instanceof GenericArrayType);
GenericArrayType genericArrayType = (GenericArrayType) result[0];
assertTrue(genericArrayType.getGenericComponentType() instanceof ParameterizedType);
ParameterizedType paramType = (ParameterizedType) genericArrayType.getGenericComponentType();
assertEquals(List.class, paramType.getRawType());
assertEquals(String.class, paramType.getActualTypeArguments()[0]);
}
@Test
public void testParam_Subclass() throws Exception {
Class<?> clazz = SubCalculator.class;
Method method = clazz.getMethod("setId", Object.class);
Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
assertEquals(String.class, result[0]);
}
@Test
public void testReturn_Anonymous() throws Exception {
Calculator<?> instance = new Calculator<Integer>();
Class<?> clazz = instance.getClass();
Method method = clazz.getMethod("getId");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertEquals(Object.class, result);
}
@Test
public void testField_GenericField() throws Exception {
Class<?> clazz = SubCalculator.class;
Class<?> declaredClass = Calculator.class;
Field field = declaredClass.getDeclaredField("fld");
Type result = TypeParameterResolver.resolveFieldType(field, clazz);
assertEquals(String.class, result);
}
@Test
public void testReturnParam_WildcardWithUpperBounds() throws Exception {
class Key {
}
@SuppressWarnings("unused")
class KeyBean<S extends Key & Cloneable, T extends Key> {
private S key1;
private T key2;
public S getKey1() {
return key1;
}
public void setKey1(S key1) {
this.key1 = key1;
}
public T getKey2() {
return key2;
}
public void setKey2(T key2) {
this.key2 = key2;
}
}
Class<?> clazz = KeyBean.class;
Method getter1 = clazz.getMethod("getKey1");
assertEquals(Key.class, TypeParameterResolver.resolveReturnType(getter1, clazz));
Method setter1 = clazz.getMethod("setKey1", Key.class);
assertEquals(Key.class, TypeParameterResolver.resolveParamTypes(setter1, clazz)[0]);
Method getter2 = clazz.getMethod("getKey2");
assertEquals(Key.class, TypeParameterResolver.resolveReturnType(getter2, clazz));
Method setter2 = clazz.getMethod("setKey2", Key.class);
assertEquals(Key.class, TypeParameterResolver.resolveParamTypes(setter2, clazz)[0]);
}
}
源码分析
主要是针对以上四种type类型的封装,三种类型获取方法入口都为同一个resolveType(returnType, srcType, declaringClass)
- 获取字段的类型入口:
resolveFieldType
- 获取方法返回值类型入口:
resolveReturnType
- 获取方法入参类型 入口:
resolveParamTypes
public class TypeParameterResolver {
public static Type resolveReturnType(Method method, Type srcType) {
// Generic: 带有泛型化参数
Type returnType = method.getGenericReturnType();
// 方法对应的类或者接口定义,[只能是public方法]
Class<?> declaringClass = method.getDeclaringClass();
// returnType: 方法返回类型
// srcType: 使用class的对象
// declaringClass:对应接口的对象
return resolveType(returnType, srcType, declaringClass);
}
public static Type resolveFieldType(Field field, Type srcType) {
Type fieldType = field.getGenericType();
Class<?> declaringClass = field.getDeclaringClass();
return resolveType(fieldType, srcType, declaringClass);
}
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;
}
// type: 方法返回类型
// srcType: 使用class的对象
// declaringClass:对应接口的对象
private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
// 泛型方法 T test();中的T
if (type instanceof TypeVariable) {
return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
}
// 方法 List<String> test();
else if (type instanceof ParameterizedType) {
return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
}
// 方法 List<String>[] test();
else if (type instanceof GenericArrayType) {
return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
}
// 基本类型double,数组等String[][];
else {
return type;
}
}
// List<String>[]
private static Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType,
Class<?> declaringClass) {
// List<String>[] -> List<String>
Type componentType = genericArrayType.getGenericComponentType();
Type resolvedComponentType = null;
// N[]
if (componentType instanceof TypeVariable) {
resolvedComponentType = resolveTypeVar((TypeVariable<?>) componentType, srcType, declaringClass);
}
// N[][]
else if (componentType instanceof GenericArrayType) {
resolvedComponentType = resolveGenericArrayType((GenericArrayType) componentType, srcType, declaringClass);
}
// List<N>[]
else if (componentType instanceof ParameterizedType) {
resolvedComponentType = resolveParameterizedType((ParameterizedType) componentType, srcType,
declaringClass);
}
if (resolvedComponentType instanceof Class) {
return Array.newInstance((Class<?>) resolvedComponentType, 0).getClass();
} else {
return new GenericArrayTypeImpl(resolvedComponentType);
}
}
// Map<String, String> -> parameterizedType -> getActualTypeArguments ->
// [String, String]
// Map<String, String> -> parameterizedType -> getRawType -> Map
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++) {
// 方法 T test();中的T
if (typeArgs[i] instanceof TypeVariable) {
args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass);
}
// 方法 List<String> test();
else if (typeArgs[i] instanceof ParameterizedType) {
args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);
}
// 泛型限定 List<? extends String> test(); --> upperBounds 上界
// 泛型限定 List<? supper String> test(); --> lowerBounds 下界
else if (typeArgs[i] instanceof WildcardType) {
args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);
} else {
args[i] = typeArgs[i];
}
}
return new ParameterizedTypeImpl(rawType, null, args);
}
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);
}
// 泛型限定 List<? extends String> test(); --> upperBounds 上界
// 泛型限定 List<? supper String> test(); --> lowerBounds 下界
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) {
result[i] = resolveWildcardType((WildcardType) bounds[i], srcType, declaringClass);
} else {
result[i] = bounds[i];
}
}
return result;
}
// typeVar:方法 T test();中的T
// srcType: 使用class的对象
// declaringClass:对应接口的对象
private static Type resolveTypeVar(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass) {
Type result = null;
Class<?> clazz = null;
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());
}
if (clazz == declaringClass) {
Type[] bounds = typeVar.getBounds();
if (bounds.length > 0) {
return bounds[0];
}
return Object.class;
}
// 继承的父类class,保留泛型信息
Type superclass = clazz.getGenericSuperclass();
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superclass);
if (result != null) {
return result;
}
// 继承的父类interfaces,保留泛型信息
Type[] superInterfaces = clazz.getGenericInterfaces();
for (Type superInterface : superInterfaces) {
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superInterface);
if (result != null) {
return result;
}
}
return Object.class;
}
// typeVar: N
// superclass: org.apache.ibatis.reflection.typeparam.Level0Mapper<E, F,
// java.lang.String>
// srcType:interface org.apache.ibatis.reflection.typeparam.Level1Mapper
// declaringClass: interface org.apache.ibatis.reflection.typeparam.Level0Mapper
// clazz:interface org.apache.ibatis.reflection.typeparam.Level1Mapper
// superclass:org.apache.ibatis.reflection.typeparam.Level0Mapper<E, F,
// java.lang.String>
private static Type scanSuperTypes(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass, Class<?> clazz,
Type superclass) {
Type result = null;
if (superclass instanceof ParameterizedType) {
ParameterizedType parentAsType = (ParameterizedType) superclass;
Class<?> parentAsClass = (Class<?>) parentAsType.getRawType();
// 对应泛型参数对比:[L, M, N]->[E, F, class java.lang.String]
// N -> class java.lang.String
if (declaringClass == parentAsClass) {
Type[] typeArgs = parentAsType.getActualTypeArguments();
TypeVariable<?>[] declaredTypeVars = declaringClass.getTypeParameters();
for (int i = 0; i < declaredTypeVars.length; i++) {
if (declaredTypeVars[i] == typeVar) {
if (typeArgs[i] instanceof TypeVariable) {
TypeVariable<?>[] typeParams = clazz.getTypeParameters();
for (int j = 0; j < typeParams.length; j++) {
if (typeParams[j] == typeArgs[i]) {
if (srcType instanceof ParameterizedType) {
result = ((ParameterizedType) srcType).getActualTypeArguments()[j];
}
break;
}
}
} else {
result = typeArgs[i];
}
}
}
} else if (declaringClass.isAssignableFrom(parentAsClass)) {
result = resolveTypeVar(typeVar, parentAsType, declaringClass);
}
} else if (superclass instanceof Class) {
if (declaringClass.isAssignableFrom((Class<?>) superclass)) {
result = resolveTypeVar(typeVar, superclass, declaringClass);
}
}
return result;
}
private TypeParameterResolver() {
super();
}
static class ParameterizedTypeImpl implements ParameterizedType {
private Class<?> rawType;
private Type ownerType;
private Type[] actualTypeArguments;
public ParameterizedTypeImpl(Class<?> rawType, Type ownerType, Type[] actualTypeArguments) {
super();
this.rawType = rawType;
this.ownerType = ownerType;
this.actualTypeArguments = actualTypeArguments;
}
@Override
public Type[] getActualTypeArguments() {
return actualTypeArguments;
}
@Override
public Type getOwnerType() {
return ownerType;
}
@Override
public Type getRawType() {
return rawType;
}
@Override
public String toString() {
return "ParameterizedTypeImpl [rawType=" + rawType + ", ownerType=" + ownerType + ", actualTypeArguments="
+ Arrays.toString(actualTypeArguments) + "]";
}
}
static class WildcardTypeImpl implements WildcardType {
private Type[] lowerBounds;
private Type[] upperBounds;
private WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) {
super();
this.lowerBounds = lowerBounds;
this.upperBounds = upperBounds;
}
@Override
public Type[] getLowerBounds() {
return lowerBounds;
}
@Override
public Type[] getUpperBounds() {
return upperBounds;
}
}
static class GenericArrayTypeImpl implements GenericArrayType {
private Type genericComponentType;
private GenericArrayTypeImpl(Type genericComponentType) {
super();
this.genericComponentType = genericComponentType;
}
@Override
public Type getGenericComponentType() {
return genericComponentType;
}
}
}