mybatis-1-泛型-Type

一.Type接口及其实现

1.ParameterizedType

表示参数化类型(带泛型的),如List<String>、Map<String,Long>、Service<User>等

方法:

1) Type getRawType();

     返回原始类型(去掉泛型);

2) Type[] getActualTypeArguments();

     获取参数化类型的类型变量或实际类型列表。如上面Map中的String、Long

3) Type getOwnerType();

     返回的是类型所属的类型。 比如 Map<String,Person> map 这个 ParameterizedType 的 getOwnerType() 为 null,而 Map.Entry<String, String>entry 的 getOwnerType() 为 Map 所属于的 Type。

2.TypeVariable

类型变量,jvm编译泛型前的信息,如List<T>、Map<k,v>,这些泛型需要运行时编译成具体类型才可以使用。

1) Type[] getBounds();获取类型变量的上边界。如:class Demo<K extends Person>,K的上边界是Person

2) D getGenericDeclaration(); 获取声明该变量的类的类型。如上面例子中的Demo

3)  String getName(); 在源码中定义的类型,如Demo中为K

3.GenericArrayType

表示数组类型,且元素为上面两种类型,如:T[]、List<String>[]

方法:Type getGenericComponentType();返回组成元素

4.WildcardType

通配符类型,如<? extends Number>

1) Type[] getUpperBounds(); 返回上边界

2) Type[] getLowerBounds(); 返回下边界

二、TypeParameterResolver类:获取字段、方法、返回值的真实类型

//字段类型
public static Type resolveFieldType(Field field, Type srcType) {
		Type fieldType = field.getGenericType();// java.util.List<java.lang.String>
		Class<?> declaringClass = field.getDeclaringClass();// class com.test.reflect.TestReflector
		return resolveType(fieldType, srcType, declaringClass);
	}

//返回值类型
public static Type resolveReturnType(Method method, Type srcType) {
		Type returnType = method.getGenericReturnType();
		Class<?> declaringClass = method.getDeclaringClass();
		return resolveType(returnType, 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;
	}



//自己实现java.lang.reflect.ParameterizedType的类,为了简化部分类
static class ParameterizedTypeImpl implements ParameterizedType
static class WildcardTypeImpl implements WildcardType
static class GenericArrayTypeImpl implements GenericArrayType

三、案例分析

    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));
public static Type resolveReturnType(Method method, Type srcType) {
	Type returnType = method.getGenericReturnType();//S
	Class<?> declaringClass = method.getDeclaringClass();//KeyBean
    //srcType =returnType
	return resolveType(returnType, srcType, declaringClass);
	}
private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
	if (type instanceof TypeVariable) {//S属于TypeVariable类型
		return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
	} else if (type instanceof ParameterizedType) {
	return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
	} else if (type instanceof GenericArrayType) {
		return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
	} else {
			return type;
		}
	}

private static Type resolveTypeVar(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass) {
	Type result = null;
	Class<?> clazz = null;
	if (srcType instanceof Class) {
		clazz = (Class<?>) srcType;//起始类 类型为class
	} else if (srcType instanceof ParameterizedType) {
		ParameterizedType parameterizedType = (ParameterizedType) srcType;
		clazz = (Class<?>) parameterizedType.getRawType();
	} else {
			throw ...
	}

	if (clazz == declaringClass) {//如果目标起始类是待搜寻方法所在的类,则只能返回上边界
		Type[] bounds = typeVar.getBounds();//获取上边界
		if (bounds.length > 0) {
			return bounds[0];//本例子中返回的是Key.class
		}
		return Object.class;//上边界默认为Object
	}

	Type superclass = clazz.getGenericSuperclass();//父类
	result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superclass);
	if (result != null) {
		return result;
	}

	Type[] superInterfaces = clazz.getGenericInterfaces();//实现的接口
	for (Type superInterface : superInterfaces) {
	result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superInterface);
		if (result != null) {
			return result;
		}
	}
	return Object.class;
	}

2)测试2,分析getKey2

Class<?> clazz = KeyBean.class;
Method getter2 = clazz.getMethod("getKey2");
assertEquals(Key.class, TypeParameterResolver.resolveReturnType(getter2, clazz));

由于起始类和方法所在类为同一个类,所以T的上边界为Key,和测试一中一样。

3)测试3,TypeParameterResolver.resolveParamTypes(Method method, Type srcType)

//获取参数的真实类型
public static Type[] resolveParamTypes(Method method, Type srcType) {
		Type[] paramTypes = method.getGenericParameterTypes();//参数为[S]
		Class<?> declaringClass = method.getDeclaringClass();//KeyBean.class
		Type[] result = new Type[paramTypes.length];//参数类型的个数
		for (int i = 0; i < paramTypes.length; i++) {
			result[i] = resolveType(paramTypes[i], srcType, declaringClass);
		}
		return result;
	}
private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
		if (type instanceof TypeVariable) {//S 为TypeVariable
			return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
		} else if (type instanceof ParameterizedType) {
			return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
		} else if (type instanceof GenericArrayType) {
			return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
		} else {
			return type;
		}
	}

同理获取类型的上边界。

 

相关推荐
©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页