利用反射操作泛型IV
通过Constructor反射解析泛型构造方法 通过Field反射解析泛型成员变量
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
1. 通过Constructor反射解析泛型构造方法
1). 构造方法和普通方法关系
(1). 构造方法和普通方法的区别
[1]. 普通方法必须有返回值类型,可以有参数
【结论】
因此Method类提供了get[Generic]ReturnType() 和get[Generic]ParameterTyps()两类方法分别对返回值类型和参数列表类型进行获取。
[2]. 构造方法必须没有返回值类型,可以有参数
【结论】
因此Constructor类仅仅提供了get[Generic]ParameterTyps()一类方法对构造方法的参数列表类型进行获取。
2). Constructor与泛型相关的方法
(1). 获取构造方法的普通参数类型数组
[1]. 源码声明:
public Class<?>[] getParameterTypes();
[2]. 返回值类型:Class元素类型的数组 Class<?>[]
(2). 获取构造方法的泛型参数类型数组
[1]. 源码声明:
public Type[] getGenericParameterTypes();
[2]. 返回值类型:Type元素类型的数组 Type[]
(3). getParameterTypes()和getGenericParameterTypes() 举例
[1]. 待测试的构造方法及其所在的类
class ClassConstructor{
//泛型构造函数
public <E extends Thread> ClassConstructor(E e, int i, ArrayList<E> al, Collection<? extends E> coll, String str,Map<String, Date>[] maps){
//.....
}
}
[2]. 测试代码
Class clazz =ClassConstructor.class;
Constructor cons=clazz.getConstructor(Thread.class, int.class, ArrayList.class, Collection.class, String.class, Map[].class);
Type[] genericParameterTypes=cons.getGenericParameterTypes();
Class[] commonParameterTypes =cons.getParameterTypes();
System.out.println("genericParameterTypes.length==commonParameterTypes.length:"+(genericParameterTypes.length ==commonParameterTypes.length));
for(int i=0; i< genericParameterTypes.length; i++){
System.out.println("Generic Type: "+ genericParameterTypes[i] +"** Common Type: "+ commonParameterTypes[i]);
}
[3]. 测试结果
【结论】由于构造方法可以看成特殊的方法,所以Constructor这两个方法的特点和同Method相应方法的特点一致(不再敖述,参见以前日志关于Method对这两个方法的对比)
(4). 通过Constructor反射解析泛型构造方法
[1]. 通过第一次关联获取Constructor对象
[2]. 通过Constructor对象的getGenericParameterTypes( )方法获取Type类型的数组
[3]. 对Type[]中每一个成员,根据参数已知得到Type接口子接口或者子类类型,强转为相应的子类接口或者子类类型的实例,根据五种类型(ParameterizedType,TypeVariable, GenericArrayType,WildcardType和Class) 的具体处理方法获取每个参数的泛型细节类型。[具体不在说明,Method反射普通方法的日志里面给出了各种详细的说明]
[4]. 这一步是[3]的替代:递归解析到最后
由于泛型可以复合成复杂的嵌套复杂类型,但是各种子类型或者子接口的处理方法每一次仅仅是对其中一层<>或者[]进行处理,所以解析之后并不是最后的原始类型,因此有必要进行解析到底。【在使用递归对任意复合类型进行彻底解剖中对这种递归操作进行了详细的阐述,这里不再重复】。
2. 通过Field反射解析泛型成员变量
1). Field与泛型有关的方法
(1). 成员变量出现泛型的位置
注意成员变量出现泛型的位置只能出现在变量的类型上,并且一个变量的类型就是唯一的。
因此Field类就提供了getGenericType()和getType()对泛型类型和普通类型的成员变量进行处理。
(2). 获取成员变量的普通类型
[1]. 源码声明:
public Class<?> getType();
[2]. 返回值类型:Class<?>
(3). 获取成员变量的泛型类型
[1]. 源码声明:
public Type getGenericType();
[2]. 返回值类型:Type
(4). getType() 和 getGenericType()的举例
[1]. 测试的成员变量及其所在的方法
class ClassField<E>{
private ArrayList<String> al1;
private ArrayList<? extends Number> al2;
private int i;
private E e;
private E[][] eArr;
}
[2]. 对Field处理泛型字段的封装
public static void analyzeFieldType(String className,String propertyName)
throws ClassNotFoundException, NoSuchFieldException{
Classclazz =Class.forName(className);
//属性是私有的 所以使用getDeclaredField方法进行获取
Fieldfield =clazz.getDeclaredField(propertyName);
TypegenericType =field.getGenericType();
Class<?>commonType =field.getType();
System.out.println("Generic Type: "+ genericType +"*******Common Type: "+ commonType);
}
[3]. 测试private ArrayList<String>al1;
{1}. 测试代码:
String className ="ClassField";
String propertyName ="al1";
analyzeFieldType(className, propertyName);
{2}. 测试结果:
Generic Type:java.util.ArrayList<java.lang.String>*******Common Type: class java.util.ArrayList
[4]. 测试private ArrayList<?extends Number> al2;
{1}. 测试代码:
String className ="ClassField";
String propertyName ="al2";
analyzeFieldType(className, propertyName);
{2}. 测试结果:
Generic Type: java.util.ArrayList<? extendsjava.lang.Number>*******Common Type: class java.util.ArrayList
[5]. 测试private int i;
{1}. 测试代码:
String className ="ClassField";
String propertyName ="i";
analyzeFieldType(className, propertyName);
{2}. 测试结果:
Generic Type:int*******Common Type: int
[6]. 测试private E e;
{1}. 测试代码:
String className ="ClassField";
String propertyName ="e";
analyzeFieldType(className, propertyName);
{2}. 测试结果:
Generic Type: E*******CommonType: class java.lang.Object
[7]. 测试private E[][]eArr;
{1}. 测试代码:
String className ="ClassField";
String propertyName ="eArr";
analyzeFieldType(className, propertyName);
{2}. 测试结果:
Generic Type:E[][]*******Common Type: class[[Ljava.lang.Object;
【总结】这两种方法的规律和Constructor、Method对应的方法规律是一样的。
如果想进行反射操作,步骤也是和这这两个类一致的。如果想进一步细化子类型,那就使用递归。这些在前面Method反射操作泛型方法都有详细的介绍,不再重复。
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------