最近在看Mybaits源码,看到参数解析的时候有这样一段代码:
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) {
args[i] = resolveTypeVar((TypeVariable>) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof ParameterizedType) {
args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);
} 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);
}
涉及到java reflect包的Type体系,对这一体系做一个学习笔记:
Type是一个接口但没有任何方法(java1.8中增加了一个方法getTypeName()),其下有四个子接口:ParameterizedType,GenericArrayType,TypeVariable和WildcardType,分别对应参数化类型,泛型数组,类型变量和通配符,还有一个熟悉的Class类,其实也是这个接口的实现类,可以理解为代表普通和基本类型。
一、ParameterizedType为参数化的类型,例如List
1、getActualTypeArguments()获取泛型中的实际类型,可能会存在多个泛型,例如Map
2、getRawType()获取泛型的声明类型或接口,对Map
3、getOwnerType()可以从源码注释中得知是获取“拥有者”,即内部类的外层类,例如Map.entry
public class TestMain {
private Map map = new HashMap<>();
public static void main(String[] args) throws NoSuchFieldException {
Field field = TestMain.class.getDeclaredField("map");
Type genericType = field.getGenericType();
ParameterizedType parameterizedType = (ParameterizedType) genericType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Type actualTypeArgument = actualTypeArguments[0];
System.out.println(actualTypeArgument); //java.lang.String
System.out.println(actualTypeArguments[1]); //java.lang.Integer
Type ownerType = parameterizedType.getOwnerType();
System.out.println(ownerType); // null
Type rawType = parameterizedType.getRawType();
System.out.println(rawType); // interface java.util.Map
System.out.println(genericType);
}
}
二、GenericArrayType为泛型数组,例如List
GenericArrayType接口中,仅有1个方法:getGenericComponentType(),返回泛型数组中元素的Type类型,即List
public class TestMain {
private List[] listString;
private List>[] listArray;
public static void main(String[] args) throws NoSuchFieldException {
Field listArray = TestMain.class.getDeclaredField("listString");
Type genericType = listArray.getGenericType();
GenericArrayType genericArrayType = (GenericArrayType) genericType;
Type genericComponentType = genericArrayType.getGenericComponentType();
System.out.println(genericComponentType); // java.util.List
Field field = TestMain.class.getDeclaredField("listArray");
Type genericType1 = field.getGenericType();
GenericArrayType genericArrayType1 = (GenericArrayType) genericType1;
Type genericComponentType1 = genericArrayType1.getGenericComponentType();
System.out.println(genericComponentType1); // java.util.List>
}
}
三、TypeVariable和WildcardType都是描述<>里面内容的接口,TypeVariable为类型参数(<>中没有?,如),在TypeVariable接口中,有4个方法,分别为getBounds()、getGenericDeclaration()、getName()和getAnnotatedBounds()(java1.8新增):
getBounds():获得该类型变量的上限,也就是泛型中extend右边的值;例如 List
getGenericDeclaration():获取声明该类型变量实体,也就是TastMain
getName():获取类型变量在源码中定义的名称,也就是TastMain
getAnnotatedBounds(): //todo
public class TestMain {
private T t;
public static void main(String[] args) throws NoSuchFieldException {
Field field = TestMain.class.getDeclaredField("t");
Type genericType = field.getGenericType();
TypeVariable typeVariable = (TypeVariable) genericType;
Type[] bounds = typeVariable.getBounds();
GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
String name = typeVariable.getName();
AnnotatedType[] annotatedBounds = typeVariable.getAnnotatedBounds();
System.out.println(bounds); //[Ljava.lang.reflect.Type;@2aae9190
System.out.println(genericDeclaration); // class test.TestMain
System.out.println(name); // T
System.out.println(annotatedBounds); //[Ljava.lang.reflect.AnnotatedType;@2f333739
}
}
四、WildcardType为通配符参数(<>中有?,如 extend Number>),WildcardType接口,有2个方法,分别为getUpperBounds()、getLowerBounds():分别是获取泛型描述的通配符的上边界和下边界(比较简单,不再举例)。