Java 反射

本文将介绍 Java 的反射机制。

一、什么是反射?

Java 的反射机制是指:

在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。

这种动态获取程序信息以及动态调用对象的功能称为 Java 语言的反射机制。反射被视为动态语言的关键。

反射适用于这样的场景:无法预知对象和类的信息,但却需要访问它的属性、调用它的方法。

二、使用反射

1. 基本步骤

  • 获取 Class 对象

    基于传入的 对象 / 全限定类名

  • 通过 Class 对象获取构造器对象、方法对象、属性对象

  • 访问

2. Class 对象

(1) 获取 Class 对象

  • 类的 class 属性 类名.class
  • 对象的 getClass() 方法 对象.getClass()
  • Class 类 forName() 方法 Class.forName(全限定类名)
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Student {
private String name;
}

// 类的 class 属性
System.out.println(Student.class);
// 对象的 getClass() 方法
System.out.println(new Student().getClass());
// Class 类 forName() 方法
System.out.println(Class.forName("Student"));

System.out.println(Student.class == new Student().getClass()
&& Student.class == Class.forName("Student"));

(2) 使用 Class 对象

可以通过 Class 对象获取构造器对象、方法对象、属性对象、注解、内部类、外部类、接口、父类等。

3. 构造器对象

(1) 获取构造器对象

  • Class对象.getConstructors():返回一个数组,由所有公共构造方法的对象构成
  • Class对象.getConstructor(参数对应的Class对象列表):返回指定的公共构造方法的对象
  • Class对象.getDeclaredConstructors():返回一个数组,由所有构造方法的对象构成
  • Class对象.getDeclaredConstructor(参数对应的Class对象列表):返回指定的构造方法的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Student {
private String name;
private int score;

public Student() {
}

public Student(String name) {
this.name = name;
}

private Student(int score) {
this.score = score;
}
}

Class<?> c = Class.forName("Student");
System.out.println(c.getConstructor(String.class));
// 无法通过getConstructor()获取私有构造方法
// System.out.println(c.getConstructor(int.class));
System.out.println(Arrays.toString(c.getConstructors()));
System.out.println(c.getDeclaredConstructor(String.class));
System.out.println(c.getDeclaredConstructor(int.class));
System.out.println(Arrays.toString(c.getDeclaredConstructors()));

(2) 使用构造器对象

1
Constructor对象.newInstance(实参)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Student {
private String name;

public Student(String name) {
this.name = name;
}
}

// 获取Class对象
Class<?> c = Class.forName("Student");
// 获取Class对象对应的构造器对象
Constructor<?> constructor = c.getConstructor(String.class);
// 通过构造器对象的newInstance()方法创建实例
System.out.println(constructor.newInstance("小张"));

4. 方法对象

(1) 获取方法对象

  • Class对象.getMethods():返回一个数组,由所有公共方法的对象构成
  • Class对象.getMethod(方法名, 参数对应的Class对象列表):返回指定的公共方法的对象
  • Class对象.getDeclaredMethods():返回一个数组,由所有方法的对象构成
  • Class对象.getDeclaredMethod(方法名, 参数对应的Class对象列表):返回指定的方法的对象

(2) 使用方法对象

1
Method对象.invoke(对象, 实参)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Student {
public void selfIntroduction() {
System.out.println("我是一个学生");
}
}

// 获取Class对象
Class<?> c = Class.forName("Student");
// 获取Class对象对应的构造器对象
Constructor<?> constructor = c.getConstructor();
// 通过构造器对象的newInstance()方法创建实例
Object obj = constructor.newInstance();
// 获取Method对象
Method method = c.getMethod("selfIntroduction");
// 调用方法
method.invoke(obj);

5. 属性对象

(1) 获取属性对象

  • Class对象.getFields():返回一个数组,由所有公共属性的对象构成
  • Class对象.getField(属性名): 返回指定的公共属性的对象
  • Class对象.getDeclaredFields():返回一个数组,由所有属性的对象构成
  • Class对象.getDeclaredField(属性名):返回指定的属性的对象

(2) 使用属性对象

1
2
Field对象.getXxx(实例对象)
Field对象.setXxx(实例对象, 值)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Student {
public int score;
}

// 获取Class对象
Class<?> clazz = Class.forName("Student");
// 获取Class对象对应的构造器对象
Constructor<?> constructor = clazz.getConstructor();
// 通过构造器对象的newInstance()方法创建实例
Object obj = constructor.newInstance();
// 获取Field对象
Field field = clazz.getField("score");
// 通过Field对象写变量
field.setInt(obj, 200);
// 通过Field对象读变量
System.out.println(field.getInt(obj));
// 打印实例
System.out.println(obj);

三、反射原理

https://www.cnblogs.com/yougewe/p/10125073.html

参考