一、什么是 Java 反射?

反射(Reflection)是 Java 提供的一种强大机制,允许程序在运行时动态加载类、创建对象、访问属性和调用方法。这使得 Java 拥有更强的灵活性和扩展能力。

反射的核心类都在 java.lang.reflect 包中,包括:

  • Class<?>:类的字节码对象
  • Field:成员变量
  • Method:类的方法
  • Constructor:构造方法

二、反射的基本使用

1. 获取 Class 对象的三种方式

1
2
3
Class<?> clazz1 = Class.forName("com.example.User"); // 推荐(可动态加载)
Class<?> clazz2 = User.class; // 编译时已知类
Class<?> clazz3 = new User().getClass(); // 运行时获取

2. 创建对象实例

1
Object obj = clazz1.newInstance(); // 类必须有无参构造器

或者使用构造函数:

1
2
Constructor<?> cons = clazz1.getConstructor();
Object obj2 = cons.newInstance();

3. 获取并设置属性

1
2
3
4
Field nameField = clazz1.getDeclaredField("name");
nameField.setAccessible(true); // 可访问私有字段
nameField.set(obj, "张三");
System.out.println(nameField.get(obj)); // 输出:张三

4. 获取并调用方法

1
2
3
Method method = clazz1.getMethod("sayHello", String.class);
Object result = method.invoke(obj, "反射");
System.out.println(result);

三、实际场景中的反射应用

✅ 1. 动态类加载(如 JDBC Driver)

1
Class.forName("com.mysql.cj.jdbc.Driver");

JDBC 在运行时加载数据库驱动类,支持多个数据库。

✅ 2. Spring IOC 容器依赖注入

Spring 底层通过反射动态创建 Bean、设置属性、注入依赖。

1
2
3
Field f = bean.getClass().getDeclaredField("repository");
f.setAccessible(true);
f.set(bean, repositoryBean);

✅ 3. 动态代理与 AOP 实现

Spring AOP、MyBatis Mapper、Dubbo 接口代理都基于反射+动态代理。

1
2
Method method = proxyMethod;
Object returnValue = method.invoke(realTarget, args);

四、进阶操作

1. 获取所有字段 / 方法 / 构造器

1
2
3
4
5
6
7
for (Field f : clazz1.getDeclaredFields()) {
System.out.println(f.getName());
}

for (Method m : clazz1.getDeclaredMethods()) {
System.out.println(m.getName());
}

2. 修改私有 final 字段(不推荐)

1
2
3
4
5
6
Field f = clazz1.getDeclaredField("CONSTANT");
f.setAccessible(true);
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(f, f.getModifiers() & ~Modifier.FINAL);
f.set(null, "newValue");

五、反射的性能与风险

性能开销大?

是的,反射操作绕过了 JVM 的正常编译优化路径,但 Java 7 之后已经进行了不少优化;如果大量频繁使用,建议:

  • 使用缓存:Map<String, Method> 缓存反射对象
  • 避免在核心循环中反射调用

安全性低?

反射突破了访问控制符,会绕过 privateprotected,因此:

  • 使用反射时应确保上下文可信
  • 不推荐用在客户端暴露逻辑(可被恶意篡改)

六、最佳实践建议

场景 是否适合使用反射
框架开发 ✅ 推荐,封装逻辑灵活
数据驱动配置 ✅ 如 JSON 转对象
高性能要求 ❌ 慎用,建议编译时注解
普通业务逻辑 ❌ 建议明确类调用

七、总结

反射不是银弹,但它是 Java 高级开发中不可或缺的工具。理解其原理和使用场景,可以帮助你更好地掌握诸如:

  • Spring IOC / AOP
  • 动态加载插件 / 类
  • 通用框架封装(如 ORM)

掌握反射,是你迈向中高级 Java 的重要一步。


以上就是我的分享啦,欢迎大佬们指点迷津,大家一起交流一起进步!