模式切换
反射机制
通过反射机制,可以更深入地控制程序运行过程。例如,可以在运行时检查类、获取类的属性和方法、调用方法、创建对象,还可以逆向控制程序的执行过程。
另外,Java 还提供了 Annotation(注解)功能,可以在类、方法、字段等元素上添加元数据,用于描述程序的结构和行为。
Class 类与 Java 反射
Java 反射(Reflection)是指在运行时动态获取类的信息,并操作类的属性、方法和构造方法。反射的核心类是 Class
,它提供了大量 API 用于操作类的结构。
表 通过反射可以访问的 Class 对象的主要描述信息
在通过 getFields()
和 getMethods()
方法依次获得权限为 public
的成员变量和方法时,将包含从父类中继承到的成员变量和方法;而通过 getDeclaredFields()
和 getDeclaredMethods()
方法获得的是当前类中声明的成员变量和方法。
下面提供了三种获取 Class 对象的方式:
- 方式 1:通过对象的
getClass()
方法
java
Person person = new Person();
Class<?> clazz1 = person.getClass();
- 方式 2:通过类的
.class
语法
java
Class<?> clazz2 = Person.class;
- 方式 3:通过
Class.forName()
java
Class<?> clazz3 = Class.forName("com.example.Person");
访问构造方法
Java 反射允许在运行时获取和调用构造方法,包括私有构造方法。
通过下列一组方法访问构造方法时,将返回 Constructor
类型的对象或数组,每个 Constructor
对象代表一个构造方法,利用 Constructor
对象可以操作相应的构造方法。
getConstructors()
:获取所有公共构造方法。getConstructors(Class<?>... parameterTypes)
:获取特定参数类型的公共构造方法。getDeclaredConstructors()
:获取所有构造方法(包括私有)。getDeclaredConstructor(Class<?>... parameterTypes)
:获取特定参数类型的构造方法。
表 Constructor 类的常用方法
通过 java.lang.reflect.Modifier
类可以解析出 getModifiers()
方法返回值所表示的修饰符信息,在该类中提供了一系列用来解析的静态方法,如 Modifier.isPublic()
、Modifier.isPrivate()
、Modifier.isProtected()
、Modifier.isStatic()
等。
表 Modifier 类的常用的解析方法
例如,判断构造方法是否为私有:
java
Constructor<?> constructor = clazz.getDeclaredConstructor();
int modifiers = constructor.getModifiers();
if (Modifier.isPrivate(modifiers)) {
System.out.println("私有构造方法");
}
获取构造方法:
java
import java.lang.reflect.Constructor;
public class ReflectionDemo {
public static void main(String[] args) throws Exception {
Class<?> clazz = Person.class;
// 获取所有构造方法(包括私有)
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
// 获取特定参数类型的构造方法
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, int.class);
System.out.println(constructor);
}
}
调用构造方法:
java
// 调用公共构造方法
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
Person person = (Person) constructor.newInstance("Alice", 25);
System.out.println(person);
// 调用私有构造方法
Constructor<?> privateConstructor = clazz.getDeclaredConstructor();
privateConstructor.setAccessible(true);
Person privatePerson = (Person) privateConstructor.newInstance();
System.out.println(privatePerson);
访问成员变量
反射允许访问类的字段(包括 private
修饰的字段)。
通过下面一组方法访问成员变量时,将返回 Field
类型的对象或数组,每个 Field
对象代表一个类的成员变量,利用 Field
对象可以操作相应的成员变量。
getFields()
:获取所有公共成员变量。getField(String name)
:获取特定名称的公共成员变量。getDeclaredFields()
:获取所有成员变量(包括私有)。getDeclaredField(String name)
:获取特定名称的成员变量。
表 Field 类的常用方法
获取成员变量:
java
import java.lang.reflect.Field;
Class<?> clazz = Person.class;
// 获取所有字段(包括私有字段)
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
// 获取特定字段
Field nameField = clazz.getDeclaredField("name");
System.out.println(nameField);
修改成员变量:
java
Person person = new Person("Bob", 30);
// 访问并修改私有字段
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true); // 解除访问限制
ageField.set(person, 35);
System.out.println(person);
访问方法
反射可以获取方法信息,并在运行时调用方法。
通过下列一组方法访问方法时,将返回 Method
类型的对象或数组,每个 Method
对象代表一个类的方法,利用 Method
对象可以操作相应的方法。
getMethods()
:获取所有公共方法。getMethod(String name, Class<?>... parameterTypes)
:获取特定名称和参数类型的公共方法。getDeclaredMethods()
:获取所有方法(包括私有)。getDeclaredMethod(String name, Class<?>... parameterTypes)
:获取特定名称和参数类型的方法。
在反射中执行具有可变数量参数的构造方法时,需要将入口参数定义成二维数组。
表 Method 类的常用方法
获取方法:
java
import java.lang.reflect.Method;
Class<?> clazz = Person.class;
// 获取所有方法(包括私有方法)
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
// 获取特定方法
Method method = clazz.getDeclaredMethod("sayHello");
System.out.println(method);
调用方法:
java
Person person = new Person("Charlie", 28);
// 调用公共方法
Method method = clazz.getMethod("sayHello");
method.invoke(person);
// 调用私有方法
Method privateMethod = clazz.getDeclaredMethod("secretMethod");
privateMethod.setAccessible(true);
privateMethod.invoke(person);