利用反射操作泛型VI
泛型类型变量的语义
GenericDeclaration接口
泛型接口TypeVariable
通过Class反射解析泛型类
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
1. 泛型类型变量的语义
(1). 以往遇见的泛型声明的基本含义 -----举例说明
[1]. 集合中常见的 public class ArrayList<E>{…}
E这个类型变量表示ArrayList集合中的元素类型是E
[2]. 反射中常见的 public class Class<T>{…}
T这个类型变量表示Class字节码类具体是什么。在Class类内部会直接操作这个类型T的实例。
(2). 泛型的语义
[1].【泛型理解1】-----子操作类
在一个类型上定义一个类型变量通常表达的含义就是原始类型会操作类型变量对应的实际类型。
[2].【泛型理解2】 -----修饰作用【这种理解更为广义】
{1}. 泛型诞生的背景 ---- 另一种理解
定义了一个含义比较笼统的类型。此时仅仅单独用这个类型表达是不准确的。为了更细致地刻画这种类型,就必须需要第二种已知的类型才能更准确地刻画这种相对笼统类型。
{2}. 泛型存在的意义
{2}1.已知的细化类型和需要定义的笼统的类型之间不存在继承关系
{2}2.已知的细化类型是可以变化的。正因为细化类型的可变性,才使得相对笼统的类型能细化成表达各种语义的参数化类型。
{2}3. 为了辅助刻画这种比较笼统的类型,将起到辅助作用的可变类型定义为这种相对笼统的新类型的类类型变量。 -----类类型变量起到的是修饰主类型的作用
e.g1 . ArrayList<String>al =new ArrayList<String>();
{理解1}. 当al调用add的时候,add操作的元素的类型就是String。这样ArrayList中操作的另一种子类型就是String。
{理解2}. ArrayList到底是什么样的集合? ArrayList是元素类型是String的集合。String是ArrayList的修饰类型,修饰ArrayList的组成元素。
******************
e.g2 . Class<String> clazz=Class.forName(“java.lang.String”);
{理解1}. 如果当成操作的子类型来理解Class定义的T并不合适。
{理解2}. Class到底是什么类型的字节码? Class表示的java.lang.String类型的字节码。String是修饰Class类型的子类型,修饰Class内部具体代表的字节码类型。
2. GenericDeclaration接口
GenericDeclaration接口基础知识
(1). GenericDeclaration接口的位置
位于java.lang.reflect反射子包中。
(2). GenericDeclaration接口类型的含义
[1]. API中的解释:所有可以声明/定义类型变量(TypeVariable)的实体的公共父接口
[2].直接实现子类:java.lang.reflect子包中的:Class,Method,Constructor
【解释】
{1}. 类型变量 可以定义在类上面(泛型类),所以GenericDeclaration实现子类有Class
{2}. 类型变量可以定义在方法上面(泛型方法),所以GenericDeclaration实现子类有Method
{3}. 类型变量可以定义在构造方法上面(泛型构造),所以GenericDeclaration实现子类有Constructor
【注意】方法的属性上面不能定义类型变量,所以GenericDeclaration的直接实现子类没有Field类。
(3). GenericDeclararion接口类型的源码
package java.lang.reflect;
public interface GenericDeclaration {
public TypeVariable<?>[] getTypeParameters();
}
(4). GenericDeclararion接口类型的唯一方法
[1]. 功能描述:
返回实现GenericDeclaration接口实现类对象声明或者定义的所有的类型变量。
[2]. 源码:public TypeVariable<?>[]getTypeParameters();
{1}. 返回数目
方法的返回值类型是数组:原因就是一个可以声明类型变量的实体可以同时声明多个类型变量。
{2}. 每一个元素类型是TypeVariable类型。
【综上】返回值类型是TypeVariable[]。
3. 泛型的TypeVariable
泛型的TypeVariable接口基础知识
(1). 重看TypeVariable的源码
package java.lang.reflect;
public interface TypeVariable<D extends GenericDeclaration> extends Type {
Type[] getBounds();
DgetGenericDeclaration();
String getName();
}
(2). 泛型接口TypeVariable<D extends GenericDeclaration>
仔细看可以知道,TypeVariable定义的时候是采用泛型限定来定义的。TypeVariable中通过泛型限定extends指定的父类正好是接口GenericDeclaration
(3). TypeVariable中泛型的含义
[1]. GenericDeclaration接口代表的是声明/定义类型变量(Type Variable)的实体,而GenericDeclaration的直接实现子类仅有Class,Method和Constructor。
[2]. 穷举原始类型TypeVariable的所有参数化类型
TypeVariable<Class>、TypeVariable<Method>和TypeVariable<Constructor>
由于Class和Constructor本身也是泛型类,但是Method本身不是泛型类,所以上面的参数化类型应该写成:
{1}. TypeVariable<Class<T>>
{2}. TypeVariable<Method>
{3}. TypeVariable<Constructor<T>>
[4]. TypeVariable<D extends GenericDeclaration>这个泛型含义什么呢?
从参数化类型入手:[从泛型的修饰角度 + GenericDeclaration理解]
{1}. TypeVariable<Class<T>>:Class<T>类上声明的TypeVariable
{2}. TypeVariable<Method>:Method类上声明的TypeVariable
{3}. TypeVariable<Constructor<T>>:Constructor类上声明的TypeVariable
【的】体现了TypeVariable中的泛型类型D对TypeVariable类型的修饰限定。--定语
【xx类上声明】是从GenericDeclaration的API的含义得到的。GenericDeclaration就代表可以声明类型变量的实体。
【结论】TypeVariable中的泛型是对声明/定义TypeVariable位置的刻画。不同的GenericDeclaration的实现子类代表了这个类型变量到底是在类上定义的,还是在方法上定义的,还是在构造上定义的?
【TypeVariable的getGenericDeclaration()方法】
D getGenericDeclaration()就是获取这个TypeVariable实例定义时候的位置
【规律】理解一个具体类的泛型类型变量的含义的方法
{1} 首先:将泛型类型变量看做这个具体类的修饰符。
{2}. 其次:如果这个类型变量有泛型限定
{2}1. 先理解泛型限定指定的上边界类的含义
{2}2. 再将上边界类的含义变成具体类的修饰符
{3}. 最后确定这个上边界类修饰限制的到底是这个具体类的什么方面即可。
(4). GenericDeclaration方法getTypeParameters()举例
[1]. 封装对TypeVariable实例的处理
public static voidanalyzeTypeVariableParts(TypeVariable<?>[] genericParameterTypes)
throws ClassNotFoundException,NoSuchMethodException{
TypeVariabletVariable=null;
Type[]bounds=null;
GenericDeclarationgenericDeclaration =null;
StringtypeVariableName =null;
for(int i=0; i<genericParameterTypes.length; i++){
tVariable=(TypeVariable)genericParameterTypes[i];
bounds=tVariable.getBounds();
genericDeclaration=tVariable.getGenericDeclaration();
typeVariableName=tVariable.getName();
System.out.println("类型变量是:"+typeVariableName);
System.out.println("父边界是:"+Arrays.asList(bounds));
System.out.println("类型变量声明的位置:"+genericDeclaration);
}
}
[2]. 测试类及其中的方法
class GenericClass<T, S>{
public <C, V> GenericClass(C c, V v){
//...
}
public <E, F> T genericMethod(E e, F f, T t, S s){
//...
return t;
}
}
[3]. 测试代码
//获取Class类对象
Class clazz =Class.forName("GenericClass");
//获取Constructor类对象
Constructor cons=clazz.getConstructor(Object.class, Object.class);
//获取Method类对象
Method method =clazz.getMethod("genericMethod", Object.class, Object.class, Object.class, Object.class);
TypeVariable<?>[] classTypeVariables=clazz.getTypeParameters();
TypeVariable<?>[]constructorTypeVariables =cons.getTypeParameters();
TypeVariable<?>[] methodTypeVariables=method.getTypeParameters();
System.out.println();
System.out.println("*******Class TypeVariables*********");
analyzeTypeVariableParts(classTypeVariables);
System.out.println();
System.out.println("*******Constructor TypeVariables*********");
analyzeTypeVariableParts(constructorTypeVariables);
System.out.println();
System.out.println("*******Method TypeVariables*********");
analyzeTypeVariableParts(methodTypeVariables);
[4]. 测试结果
4. 通过Class反射解析泛型类
(1). 泛型类中类型变量出现的位置
[1]. 仅仅会出现在类名之后,“{”之前。这个位置<>中是类的类型变量的定义位置。
[2]. 所以这个位置出现的泛型只能是类型变量(TypeVariable)
[3]. 而不会出现参数化类型(ParameterizedType),通配符表达式(WildcardType),泛型数组(GenericArrayTypeType)。
(2). 通过Class反射解析泛型类的核心思想
[1]. 泛型类上仅仅存在类型变量的定义,不存在类型变量的使用。
[2]. Class这个类是GenericDeclaration接口的直接子类,所以直接使用 GenericDeclaration的方法publicTypeVariable<?>[] getTypeParameters();直接获取到这个泛型类中声明的类型变量数组就完成了反射对泛型类的分析。
(3). 通过Class反射解析泛型类的步骤
[1]. 获取Class对象
三种方法:静态方法(Class.forName())+ 动态方法(getClass()) +静态成员变量(xxx.class)
[2]. 通过Class的getTypeParameters()获取定义在泛型类上面的类型变量数组
[3]. 解析获取到的类型变量数组 TypeVariable<?>[]
【示例代码】上面的示例代码就有。
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------