反射

反射

  • java 反射(Reflection)是一个强大的特性,
  • 它允许程序在运行时查询、访问和修改类、接口、字段和方法的信息
  • 反射提供了一种动态地操作类的能力,这在很多框架和库中被广泛使用,例如Spring框架的依赖注入。

反射 API

  • Java 的反射 API 提供了一系列的类和接口来操作 Class 对象。
  • java.lang.reflectJava 反射机制的核心包,提供了操作类及其成员(字段、方法、构造函数等)的类和接口。通过这些 API,开发者可以在运行时动态地查询和修改类的结构。

常用

API作用
java.lang.Class表示类的对象。提供了方法来获取类的字段、方法、构造函数等
java.lang.reflect.Field表示类的字段(属性)。提供了访问和修改字段的能力。
java.lang.reflect.Method表示类的方法。提供了调用方法的能力。
java.lang.reflect.Constructor表示类的构造函数。提供了创建对象的能力。

Class类相关

表示类的对象,提供了获取类信息的方法,如字段、方法、构造函数等。

API作用
getFields()获取类的获取所有公共字段。
getDeclaredFields()获取所有声明的字段,包括私有字段。
getField(String name)根据名称获取公共字段。
getDeclaredField(String name)根据名称获取声明的字段,包括私有字段。
getMethods()获取类的所有公共方法。
getDeclaredMethods()获取所有声明的方法,包括私有方法。
getMethod(String name, Class<?>... parameterTypes)根据名称和参数类型获取公共方法。
getDeclaredMethod(String name, Class<?>... parameterTypes)根据名称和参数类型获取声明的方法,包括私有方法。
getConstructors()获取类的所有公共构造函数。
getDeclaredConstructors()获取所有声明的构造函数,包括私有构造函数。
getConstructor(Class<?>... parameterTypes)根据参数类型获取公共构造函数。
getDeclaredConstructor(Class<?>... parameterTypes)根据参数类型获取声明的构造函数,包括私有构造函数。
getSuperclass()获取父类。
getInterfaces()获取类实现的接口。

Field类相关

表示类的字段(属性),提供了访问和修改字段的能力。

api作用
get(Object obj)获取字段的值
set(Object obj, Object value)设置字段的值
getType()获取字段的类型
getName()获取字段的名称

Method类相关

表示类的方法,提供了调用方法的能力。

api作用
invoke(Object obj, Object... args)调用方法
getParameterTypes()获取方法的参数类型
getReturnType()获取方法的返回类型
getName()获取方法的名称
getModifiers()获取方法的修饰符

Constructor类相关

表示类的构造函数,提供了创建对象的能力。

api作用
newInstance(Object... initargs)创建一个新实例,使用指定的构造函数参数。
getParameterTypes()获取构造函数的参数类型
getName()获取构造函数的名称
getModifiers()获取构造函数的修饰符
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionExample {

    public static void main(String[] args) throws Exception {
        // 获取 Class 对象
        Class<?> clazz = Person.class;
       
        // 创建对象
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        Object person = constructor.newInstance("John", 30);
       
        // 访问字段
        Field nameField = clazz.getDeclaredField("name");
        nameField.setAccessible(true);
        System.out.println("Name: " + nameField.get(person));
       
        // 修改字段
        nameField.set(person, "Doe");
        System.out.println("Updated Name: " + nameField.get(person));
       
        // 调用方法
        Method greetMethod = clazz.getMethod("greet", String.class);
        greetMethod.invoke(person, "World");
    }
}

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void greet(String message) {
        System.out.println(name + " says: " + message);
    }
}

工作流程

  1. 获取 Class 对象,首先获取目标类的 Class 对象。
  2. 获取 Field 对象,通过 Class 对象,可以获取类的字段、方法、构造函数等信息
  3. 操作成员:通过反射 API 可以读取和修改字段的值、调用方法以及创建对象。

获取 Class 对象

每个类在 JVM 中都有一个与之相关的 Class 对象。可以通过以下方式获取 Class 对象:

通过类字面量获取:

Class<?> clazz = String.class;

通过对象实例获取

String str = "Hello World";
Class<?> clazz = str.getClass();

通过 Class.forName()方法获取

Class<?> clazz = Class.forName("java.lang.String");

创建对象

可以使用反射动态创建对象:

Class<?> clazz = Class.forName("java.lang.String");
Object obj = clazz.getDeclaredConstructor().newInstance();

访问字段

可以通过反射访问和修改类的字段:

Class<?> clazz = Person.class;
Field field = clazz.getDeclaredField("name");
field.setAccessible(true); // 如果字段是私有的,需要设置为可访问
Object value = field.get(personInstance); // 获取字段值
field.set(personInstance, "New Name"); // 设置字段值

调用方法

可以通过反射调用类的方法:

Class<?> clazz = Person.class;
Method method = clazz.getMethod("sayHello");// 获取无参方法
method.invoke(personInstance);// 调用方法

Method methodWithArgs = clazz.getMethod("greet", String.class);// 获取有参方法 String.class 是参数类型
methodWithArgs.invoke(personInstance, "World");// 调用方法,传入参数

获取构造函数

可以通过反射获取类的构造函数:

Class<?> clazz = Person.class;//通过反射获取类
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);//获取构造函数 String.class 是参数类型 int.class 是参数类型
Object obj = constructor.newInstance("John", 30);// 通过构造函数创建对象

获取接口和父类

可以使用反射获取类实现的接口和父类:

Class<?> clazz = Person.class;// 通过反射获取类

Class<?>[] interfaces = clazz.getInterfaces();// 获取所有接口
for (Class<?> i : interfaces) {
    System.out.println("Interface: " + i.getName());// 打印接口名称
}

Class<?> superClass = clazz.getSuperclass();// 获取父类
System.out.println("Superclass: " + superClass.getName());// 打印父类名称
上次更新 2025/11/25 10:15:52