外观
Java 的反射原理
⭐ 题目日期:
小红书 - 2024/11/11
📝 题解:
反射是 Java 提供的一种在运行时动态获取类信息、操作类属性和方法的机制,广泛应用于框架开发、动态代理、测试工具等场景。以下是其核心概念、使用方法和实际应用:
一、反射的核心类
Class
类:表示类或接口的元数据,是反射的入口。Field
类:表示类的成员变量。Method
类:表示类的方法。Constructor
类:表示类的构造方法。
二、获取 Class 对象的三种方式
- 通过类名获取:
Class<?> clazz = String.class;
- 通过对象实例获取:
String str = "Hello";
Class<?> clazz = str.getClass();
- 通过全限定类名动态加载:
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;
}
);
四、反射的优缺点
五、实际应用场景
- 框架开发:
- Spring IOC:通过反射动态创建 Bean 并注入依赖。
- JUnit:反射调用测试方法。
- 动态代理:
- AOP(面向切面编程):拦截方法调用实现日志、事务管理。
- 序列化与反序列化:
- Jackson/Gson:反射解析 JSON 字段到 Java 对象。
- 插件化架构:
- 动态加载模块:通过
ClassLoader
加载外部 JAR 包的类。
- 动态加载模块:通过
六、性能优化建议
- 缓存反射对象: 将频繁使用的
Method
、Field
缓存,避免重复查找。
private static final Method setNameMethod = User.class.getMethod("setName", String.class);
- 使用
setAccessible(true)
谨慎: 仅必要时突破访问限制,避免滥用。 - 选择替代方案:
- LambdaMetafactory:Java 8+ 的方法句柄(Method Handle)提升性能。
- 代码生成库:如 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 生态中主流框架的设计原理,并灵活解决特定场景下的技术挑战。