预备知识
动态语言和静态语言
- 动态语言
- 是一种可以在运行时改变其结构的语言,例如新的函数、对象、甚至代码可以在运行时被引进,已有的函数可以被删除或是 其他结构上的变化。通俗的讲就是在运行时代码可以根据某些条件改变自身结构
- 举例:Object-C、C#、JavaScript、PHP、Python
- 静态语言
- 与动态语言相对的,运行时结构不可改变的语言
- C、C++、JAVA
- java不是动态语言,但通过反射机制实现类似动态语言的特性
Class对象
获取Class对象
通过类名获得:
类名.class
, 最高效通过对象获得:
对象.getClass()
- 通过forname获得 :
Class.forName(" ")
- 通过内置类型的包装类获得:
内置类型包装类.TYPE
- 已知一个Class,获取其获得父类Class:
Class.getSuperclass()
哪些类型可以有Class对象
- 类
- 接口
- 数组(同一维度的数组是同一个Class对象,不同维度的数组是不同的Class对象)
- 注解
- 枚举
- 基本数据类型
- void
- Class
使用反射
反射操作Class对象
JVM在第一次读取到一中class
类型时,就将其加载入内存。每加载一种class
,JVM就为其创建一个Class
类型的实例,并关联起来。这个Class
实例是在JVM内部创建的,构造方法是private
,只有JVM能创建Class
实例,我们自己的JAVA程序无法创建。
通过引入import java.lang.reflect.Field;
可以通过Field
获取一个类的字段,进而通过get
和set
方法获取和修改对象的字段值
通过引入import java.lang.reflect.Method;
可以通过Method
获取一个类的方法,进而通过invoke
调用方法
通过引入import java.lang.reflect.Constructor;
可以通过Constructor获取一个类的构造方法,进而通过newInstance()
方法构造一个类的实例(也可以在获取Class的newInstance方法,但是这样做只能调用无参构造方法).
我们还可以通过getSuperclass()
获取一个类的父类,通过getInterfaces()
获取一个类的接口,
反射操作泛型
为了反射操作泛型,JAVA新增了几种类型
- ParameterizedType :表示一种参数化类型,比如Collection
- GenericArrayType :表示一种元素类型时参数化类型或者类型变量的数组类型
- TypeVariable:是各种类型变量的通用父接口
- WildcardType:代表一种通配符类型表达式
如图所示:
test01是一个以泛型为参数的方法,当我们对test01使用method.getGenericParameterTypes() 方法时,只能得到Map
以上就是泛型作为函数参数时通过反射获取的方法,当泛型作为函数返回值时,我们只需要将method.getGenericParameterTypes() 换成method.getGenericReturnTypes() 即可。
反射操作注解
获取一个类的全部注解: getAnnotations()
获取指定注解 :getAnnotation(注解.class)
获取注解后,可以进一步通过 “.字段”来获取注解的字段值