Java 反射是指在运行时检查、获取和操作类的信息和对象的能力。通过反射机制,可以在运行时动态地获取类的结构信息(如字段、方法、构造函数等)、调用类的方法、创建对象实例等。反射机制为编写灵活、通用、可扩展的代码提供了支持,但同时也会增加代码的复杂性和性能开销。

以下是 Java 反射的主要概念和使用方法:

Class 类:Class 类是 Java 反射的核心类之一,它表示运行时类的信息。通过 Class 类可以获取类的结构信息(如字段、方法、构造函数等)、创建类的对象实例以及执行类的方法等操作。

获取 Class 对象:可以通过多种方式获取 Class 对象,包括使用类的 .class 属性、调用类的 getClass() 方法、使用 Class.forName() 方法等。

获取类的结构信息:通过 Class 对象可以获取类的字段、方法、构造函数等信息,包括获取公共字段、私有字段、静态字段、公共方法、私有方法、构造函数等。

创建对象实例:通过 Class 对象可以创建类的对象实例,包括通过默认构造函数、指定构造函数、无参构造函数等方式创建对象。

调用方法:通过 Method 类可以调用类的方法,包括调用公共方法、私有方法、静态方法等。可以使用 Method.invoke() 方法调用方法并传递参数。

操作字段:通过 Field 类可以操作类的字段,包括获取字段值、设置字段值等。可以使用 Field.get() 方法获取字段值,Field.set() 方法设置字段值。

操作构造函数:通过 Constructor 类可以操作类的构造函数,包括获取构造函数、创建对象实例等。可以使用 Constructor.newInstance() 方法创建对象实例。

动态代理:Java 反射还可以实现动态代理,即在运行时动态地创建代理对象,并在代理对象中实现对目标对象的方法调用,以实现额外的逻辑或功能。

适用场景:Java 反射通常用于需要在运行时动态地操作类和对象的场景,如编写通用的框架、库或工具、实现依赖注入、实现ORM(Object-Relational Mapping) 框架等。但需要注意,反射机制可能会降低代码的性能和安全性,因此应该谨慎使用,并考虑是否有更好的替代方案

反射示例

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 = MyClass.class;

        // 获取类的字段信息
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            System.out.println("字段名:" + field.getName() + ", 类型:" + field.getType());
        }

        // 获取类的方法信息
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println("方法名:" + method.getName() + ", 返回类型:" + method.getReturnType());
        }

        // 获取类的构造函数信息
        Constructor<?>[] constructors = clazz.getDeclaredConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("构造函数:" + constructor);
        }

        // 创建对象实例
        Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, int.class);
        constructor.setAccessible(true); // 设置可访问私有构造函数
        MyClass obj = (MyClass) constructor.newInstance("Hello", 123);

        // 调用方法
        Method method = clazz.getDeclaredMethod("printInfo");
        method.setAccessible(true); // 设置可访问私有方法
        method.invoke(obj);

        // 操作字段
        Field field = clazz.getDeclaredField("message");
        field.setAccessible(true); // 设置可访问私有字段
        String value = (String) field.get(obj);
        System.out.println("字段值:" + value);
    }
}

class MyClass {
    private String message;
    private int number;

    private MyClass(String message, int number) {
        this.message = message;
        this.number = number;
    }

    private void printInfo() {
        System.out.println("Message: " + message + ", Number: " + number);
    }
}

JAVA动态代理示例,通过反射实现

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义接口
interface Subject {
    void doSomething();
}

// 实现接口的类
class RealSubject implements Subject {
    @Override
    public void doSomething() {
        System.out.println("RealSubject: Doing something...");
    }
}

// 实现 InvocationHandler 接口
class DynamicProxy implements InvocationHandler {
    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用目标方法前添加额外的逻辑
        System.out.println("Before method execution...");

        // 调用目标方法
        Object result = method.invoke(target, args);

        // 在调用目标方法后添加额外的逻辑
        System.out.println("After method execution...");

        return result;
    }
}

public class ProxyExample {
    public static void main(String[] args) {
        // 创建目标对象
        RealSubject realSubject = new RealSubject();

        // 创建动态代理对象
        Subject proxy = (Subject) Proxy.newProxyInstance(
                realSubject.getClass().getClassLoader(),
                realSubject.getClass().getInterfaces(),
                new DynamicProxy(realSubject)
        );

        // 调用代理对象的方法
        proxy.doSomething();
    }
}

在以前jdbc中,获取到数据库连接查询到数据,也是通过反射方式,获取类的字段信息,并从结果集中获取对应字段的值