反射(Reflection)
Qtrue_Akira2025年12月9日大约 4 分钟
反射就是:加载类,并运行以编程的方式解剖类中的各种成分(成员变量、方法、构造器等),从而实现动态调用的一种机制。
通过反射,开发者可以动态地创建对象、调用方法以及访问和修改字段,即使这些成员在编译时是不可见的。
在Java中,每个类在运行时都会对应一个Class对象。通过这个Class对象,我们可以获取类的各种信息,并进行动态操作。获取Class对象的常用方法有三种:
- 使用类的静态属性
class:Class c1 = MyClass.class;
- 使用
Class.forName()方法(需要处理ClassNotFoundException异常):try {
Class c2 = Class.forName("com.example.MyClass");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
- 使用对象的
getClass()方法:MyClass myObject = new MyClass();
Class c3 = myObject.getClass();
通过Class对象,我们可以获取类的各种成员信息,包括成员变量、成员方法和构造器。
| 方法 | 说明 |
|---|
| Constructor<?>[] getDeclaredConstructors() | 获取所有构造器(只要存在就能获取) |
| Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) | 获取指定参数类型的构造器(只要存在就能获取) |
| Constructor<?>[] getConstructors() | 获取所有构造器(只能获取public修饰的) |
| Constructor<T> getConstructor(Class<?>... parameterTypes) | 获取指定参数类型的构造器(只能获取public修饰的) |
| 方法 | 说明 |
|---|
| Field[] getDeclaredFields() | 获取所有成员变量(只要存在就能获取) |
| Field getDeclaredField(String name) | 获取指定名称的成员变量(只要存在就能获取) |
| Field[] getFields() | 获取所有成员变量(只能获取public修饰的) |
| Field getField(String name) | 获取指定名称的成员变量(只能获取public修饰的) |
| 方法 | 说明 |
|---|
| Method[] getDeclaredMethods() | 获取所有成员方法(只要存在就能获取) |
| Method getDeclaredMethod(String name, Class<?>... parameterTypes) | 获取指定名称和参数类型的成员方法(只要存在就能获取) |
| Method[] getMethods() | 获取所有成员方法(只能获取public修饰的) |
| Method getMethod(String name, Class<?>... parameterTypes) | 获取指定名称和参数类型的成员方法(只能获取public修饰的) |
通过获取到的构造器、成员变量和成员方法,我们可以动态地创建对象、访问和修改字段,以及调用方法。
- 动态创建对象可以使用
Constructor类的newInstance()方法:
| Constructor提供的方法 | 说明 |
|---|
| T newInstance(Object... initargs) | 使用指定的参数创建对象,并返回 |
| void setAccessible(boolean flag) | 设置是否允许访问私有构造器(暴力反射) |
- 访问和修改字段可以使用
Field类的get()和set()方法:
| Field提供的方法 | 说明 |
|---|
| Object get(Object obj) | 获取指定对象的字段值,并返回 |
| void set(Object obj, Object value) | 设置指定对象的字段值为指定值 |
| void setAccessible(boolean flag) | 设置是否允许访问私有字段(暴力反射) |
- 调用方法可以使用
Method类的invoke()方法:
| Method提供的方法 | 说明 |
|---|
| Object invoke(Object obj, Object... args) | 调用指定对象的成员方法,并传递参数,返回方法的返回值 |
| void setAccessible(boolean flag) | 设置是否允许访问私有方法(暴力反射) |
- 基本作用:可以得到一个类的全部成分并进行动态调用。
- 可以破坏封装性:通过反射可以访问和修改类的私有成员。
- 可以绕过泛型检查:通过反射可以操作泛型类型的成员,绕过编译时的类型检查。
- 最重要的作用:适合做Java的框架,使得这些框架能够动态地操作类和对象,从而实现依赖注入、对象关系映射等功能。