目录
Java的反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法;对于任意一个对象,都能够调用它的任何方法和属性。这种动态获取类的信息以及动态调用方法的功能称为Java语言的反射(reflection)机制。
Java程序中一些对象在运行时会出现两种类型:运行时类型和编译时类型,例如一个向上转型的代码:Bird bird = new Animal();其中,bird在编译时类型为Bird,运行时类型为Animal,通过反射机制就能在程序运行时发现该对象和类的真实信息。
| Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
| Field类 | 代表类的成员变量/字段 |
| Method类 | 代表类的方法 |
| Constructor类 | 代表类的构造方法 |
在反射之前,我们需要先拿到当前需要反射的类的Class对象,然后通过Class对象调用相关的方法,来达到反射的目的。
获得Class对象的三种方式:
(1)使用Class.forName方法("类的全路径名");
(2)使用需要反射的类名调用class方法;
(3)使用需要反射的类的对象调用getClass方法

但是通过三种方式获取的Class对象都是相同的,也就是说,一个类只有一个对应的Class对象:

| Class类中常用获得类相关的方法 | |
|---|---|
| 方法 | 作用 |
| getClassLoader() | 获得类的加载器 |
| getDeclaredClasses() | 返回一个数组,数组中包含该类中所有类和接口类的对象 |
| forName(String classRoad) | 根据类的路径返回类的Class对象(该方法是静态成员方法) |
| newInstacne() | 创建类的实例 |
| getName() | 获得类的完整路径名 |
获得类中构造器相关的方法(返回值为Constructor类型相关)
| 方法 | 作用 |
| getConstructor(Class...>parameterTypes) | 获得该类中与参数类型匹配的公有的构造方法 |
| getConstructors() | 获得该类中所有公有的构造方法 |
| getDeclaredConstructor(Class...>parameterTypes) | 获得该类中与参数类型匹配的构造方法 |
| getDeclaredConstructors() | 获得该类中所有构造方法 |
示例:
创建一个Student类:
- public class Student {
- public String name;//公共的成员变量
-
- private int id = 1;//私有的成员变量
-
- public Student(){
- System.out.println("公共的构造方法");
- }
-
- private Student(int id){
- this.id = id;
- System.out.println("私有的构造方法");
- }
-
- public void func(){
- System.out.println("公共的成员方法");
- }
-
- private void func2(String s){
- System.out.println(s);
- }
-
- @Override
- public String toString() {
- return "Student{" +
- "name='" + name + '\'' +
- ", id=" + id +
- '}';
- }
- }
在同一个包中的Test类中通过Student类私有的构造方法创建一个Student对象:
- public class Test {
- public static void reflectPrivateConstructor(){
- try {
- //获得Class对象
- Class> c1 = Class.forName("reflect.Student");
- //调用getDeclaredField(String name)方法
- Constructor> constructor = c1.getDeclaredConstructor(int.class);
- //调用setAccessible(boolean)后可修改访问权限
- constructor.setAccessible(true);
- //通过Constructor对象创建Student对象
- Student student = (Student) constructor.newInstance(100);
- //输出创建好的Student对象
- System.out.println(student);
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) throws ClassNotFoundException {
- reflectPrivateConstructor();
- }
- }
代码运行结果:

获得类中字段相关的方法(返回值为Field类型相关)
| 方法 | 作用 |
| getField(String name) | 获得该类中某个公有的字段 |
| getFields() | 获得该类中所有公有的字段 |
| getDeclaredField(String name) | 获得该类中某个字段 |
| getDeclaredFields() | 获得该类中所有字段 |
示例:
反射Student类中的私有成员变量
- public class Test {
- public static void reflectPrivateField(){
- try {
- //获得Class对象
- Class> c1 = Class.forName("reflect.Student");
- //getDeclaredField(String name)方法
- Field field = c1.getDeclaredField("id");
- //调用setAccessible(boolean)后可修改访问权限
- field.setAccessible(true);
- //通过Class类反射一个Student对象
- Student student = (Student) c1.newInstance();
- //修改指定Student对象的静态成员变量:id = 500
- field.set(student,500);
- //输出Student对象
- System.out.println(student);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (NoSuchFieldException e) {
- e.printStackTrace();
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- reflectPrivateField();
- }
- }
代码运行结果:

获得类中方法相关的方法(返回值为Method类型相关)
| 方法 | 作用 |
| getMethod(String name,Class...>parameterTypes) | 获得该类中某个公有的方法 |
| getMethods() | 获得该类中所有公有的方法 |
| getDeclaredMethod(String name,Class...>parameterTypes) | 获得该类中某个方法 |
| getDeclaredMethods() | 获得该类中所有方法 |
示例:
反射Student类中的私有成员方法
- public class Test {
- public static void reflectPrivateMethod(){
- try {
- //获得Class对象
- Class> c1 = Class.forName("reflect.Student");
- //调用getDeclaredMethod(String name,Class...>parameterTypes)方法
- Method method = c1.getDeclaredMethod("func2",String.class);
- //获取私有的属性或方法一般都要调用setAccessible(boolean)方法
- method.setAccessible(true);
- //通过Class类反射一个Student对象
- Student student = (Student) c1.newInstance();
- //Method对象调用invoke方法
- //让指定的Student对象调用指定的私有方法并传参
- method.invoke(student,"通过反射机制调用Student类的私有方法");
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- }
- }
-
- public static void main(String[] args) {
- reflectPrivateMethod();
- }
- }
代码运行结果:

(1)对于任意一个类,都能够获得这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;
(2)增加程序的灵活性和扩展性,降低耦合性。
(1)使用反射会导致程序效率降低(为了获得一个类的对象,调用了Class类中的多个方法);
(2)反射机制绕过了源代码,可能会带来维护问题。