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 |
|
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 |
|
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 |
|
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);
三、反射原理
参考
疯狂 Java 讲义