Skip to content

Java 的反射原理

约 729 字大约 2 分钟

Java基础小红书

2025-03-14

⭐ 题目日期:

小红书 - 2024/11/11

📝 题解:

反射是 Java 提供的一种在运行时动态获取类信息、操作类属性和方法的机制,广泛应用于框架开发、动态代理、测试工具等场景。以下是其核心概念、使用方法和实际应用:


一、反射的核心类

  1. Class:表示类或接口的元数据,是反射的入口。
  2. Field:表示类的成员变量。
  3. Method:表示类的方法。
  4. Constructor:表示类的构造方法。

二、获取 Class 对象的三种方式

  1. 通过类名获取
Class<?> clazz = String.class;
  1. 通过对象实例获取
String str = "Hello";
Class<?> clazz = str.getClass();
  1. 通过全限定类名动态加载
Class<?> clazz = Class.forName("java.lang.String");

三、反射的常用操作

1. 创建对象实例
// 无参构造
Class<?> clazz = User.class;
User user = (User) clazz.newInstance();
// 有参构造
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
User user = (User) constructor.newInstance("Alice", 25);
2. 调用方法
Method method = clazz.getMethod("setName", String.class);
method.invoke(user, "Bob");  // 等价于 user.setName("Bob");
3. 访问字段
Field field = clazz.getDeclaredField("age");
field.setAccessible(true);  // 突破私有权限限制
field.set(user, 30);        // 设置字段值
int age = (int) field.get(user);  // 获取字段值
4. 动态代理(基于接口)
interface Service {
    void serve();
}
Service proxy = (Service) Proxy.newProxyInstance(
    Service.class.getClassLoader(),
    new Class[]{Service.class},
    (proxyObj, method, args) -> {
        System.out.println("Before service");
        method.invoke(target, args);  // 调用实际方法
        return null;
    }
);

四、反射的优缺点

img


五、实际应用场景

  1. 框架开发
    1. Spring IOC:通过反射动态创建 Bean 并注入依赖。
    2. JUnit:反射调用测试方法。
  2. 动态代理
    1. AOP面向切面编程):拦截方法调用实现日志、事务管理。
  3. 序列化与反序列化
    1. Jackson/Gson:反射解析 JSON 字段到 Java 对象。
  4. 插件化架构
    1. 动态加载模块:通过 ClassLoader 加载外部 JAR 包的类。

六、性能优化建议

  1. 缓存反射对象: 将频繁使用的 MethodField 缓存,避免重复查找。
private static final Method setNameMethod = User.class.getMethod("setName", String.class);
  1. 使用 setAccessible(true) 谨慎: 仅必要时突破访问限制,避免滥用。
  2. 选择替代方案
    1. LambdaMetafactory:Java 8+ 的方法句柄(Method Handle)提升性能。
    2. 代码生成库:如 ByteBuddy、CGLIB 生成动态类。

七、代码示例:反射实现简易依赖注入

public class SimpleContainer {
    private Map<Class<?>, Object> beans = new HashMap<>();
    public void register(Class<?> clazz) throws Exception {
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
        Object instance = constructor.newInstance();
        beans.put(clazz, instance);
    }
    public <T> T getBean(Class<T> clazz) {
        return clazz.cast(beans.get(clazz));
    }
    // 使用示例
    public static void main(String[] args) throws Exception {
        SimpleContainer container = new SimpleContainer();
        container.register(UserService.class);
        UserService service = container.getBean(UserService.class);
    }
}

八、总结

反射是 Java 动态能力的核心,适用于框架、工具和复杂业务场景,但需谨慎使用以避免性能和安全问题。掌握反射机制,能够深入理解 Java 生态中主流框架的设计原理,并灵活解决特定场景下的技术挑战。