小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
什么是反射?
在程序运行时,对于任意一个类都能获取其所有属性和方法,对于任意一个对象都能够调用其所有方法,这种动态获取类和对象的信息、动态调用对象的方法的功能称为java语言的反射机制。
获取类的所有属性和方法
分为两步:
1. 获得class对象。每个类被加载后,jvm会为该类生成一个对应的Class对象。获取某个类的Class对象的方法有三种:
① 使用Class类的静态方法forName(String clazzName)。该方法需要传入某个类的全限定类名。
② 访问某个类的class属性来获取。例如,Person.class将返回Person类对应的Class对象。
③ 调用某个对象的getClass()方法。
2. 通过获得的class对象获取信息:
① 获取构造器:
| 方法 | 说明 |
| ConstructorgetConstructor(Class…parameterTypes) | 返回指定形参列表的public构造器 |
| Constructor[]getConstructors() | 返回所有public构造器 |
| ConstructorgetDeclaredConstructor(Class…parameterTypes) | 返回指定形参列表的构造器,与构造器的访问权限无关 |
| Constructor[]getDeclaredConstructors() | 返回所有构造器,与构造器的访问权限无关 |
② 获取方法
| 方法 | 说明 |
| Method getMethod (String name, Class…parameterTypes) | 返回方法名为name, 带指定形参列表的public方法 |
| Method[] getMethods() | 返回所有public方法 |
| Method getDeclaredMethod(String name, Class…parameterTypes) | 返回方法名为name, 指定形参列表的方法,与方法的访问权限无关 |
| Method[] getDeclaredMethods() | 返回所有方法,与方法的访问权限无关 |
③ 获取成员变量
| 方法 | 说明 |
| Field getField (String name) | 返回指定名称的public成员变量 |
| Field[] getFields () | 返回所有public成员变量 |
| Field getDeclaredField(String name) | 返回指定名称的成员变量,与成员变量的访问权限无关 |
| Field[] getDeclaredFields() | 返回所有成员变量,与成员变量的访问权限无关 |
除了上述信息外,还可以获取class对象的Annotation、内部类、修饰符等,由于用的不多就不一一列举了,想了解的同学请查阅官方文档。
使用反射生成并操作对象
1. 生成对象
有两种方式:
① 使用class对象的newInstance()方法创建class对象对应类的实例,这种方法要求class对象对应类有默认构造器。执行newInstance()方法时实际上就是利用默认构造起来创建该类的实例
② 先使用class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法创建实例。
2. 调用方法
通过class对象获取Method对象后,调用Method对象的invoke()方法来调用。若Method对象对应的方法是private的,可以先通过Method对象.setAccessible(true)来取消java语言的访问权限检查。
3. 访问、修改成员变量的值
通过class对象获取Field对象后,通过如下两组方法读取或设置成员变量值
① getXxx(Object obj):获取obj对象的该成员变量值。此处Xxx对应8种基本类型,如果该成员变量是引用类型,则去掉get后面的Xxx。
② setXxx(Object obj, val):将obj对象的该成员变量设置成val. 此处Xxx对应8种基本类型,如果该成员变量是引用类型,则去掉set后面的Xxx。