454. Java 反射 - 简介

454. Java 反射 - 简介

1. 什么是 Reflection?

Reflection(反射) 允许 Java 程序在运行时(Runtime)检查或修改应用的行为。

你可以把反射想象成一面镜子

  • 对象照镜子:通过反射,一个对象可以“看到”自己拥有哪些属性(Field)、方法(Method)和构造器(Constructor)。
  • 动态操作:不仅能看,你还可以通过镜子在运行时动态地改变字段值、调用方法,甚至创建新的对象实例。

2. 核心 API 操作

反射的核心在于获取类的 Class 对象,进而操作其内部结构。

2.1 获取 Class 对象

有三种常见方式获取一个类的 Class 对象:

// 1. 通过类字面量
Class<?> clazz1 = String.class;

// 2. 通过对象实例
Class<?> clazz2 = "Hello".getClass();

// 3. 通过全限定类名(常用于动态加载)
Class<?> clazz3 = Class.forName("java.lang.String");

2.2 构造器、字段与方法

以下是操作一个普通 Java 类(如 Person)的常用 API:

操作对象 核心方法 示例代码
构造器 (Constructor) getConstructor() Constructor<Person> c = Person.class.getConstructor(); Person p = c.newInstance(); // 动态创建对象
字段 (Field) getDeclaredFields() Field f = Person.class.getDeclaredField("name"); f.setAccessible(true); // 访问私有成员 f.set(p, "Alice"); // 设置值
方法 (Method) getMethods() Method m = Person.class.getMethod("setAge", int.class); m.invoke(p, 25); // 动态调用方法

3. Reflection 的常见用途

🧩 扩展性与插件系统

反射允许根据类的全限定名动态加载用户自定义类。这在 Spring 框架(依赖注入) 和各类 插件系统 中极为常见,开发者无需在代码中硬编码具体的类名。

🔍 开发工具与 IDE

IDE(如 IntelliJ 或 Eclipse)的类浏览器、自动代码提示功能,都是通过反射枚举类的字段、方法和接口来实现的。

🐞 自动化测试与调试

  • JUnit:自动发现并执行带有 @Test 注解的方法。
  • 调试器:在程序运行时检查对象的私有字段状态。

4. Reflection 的优缺点(双刃剑)

反射是一把功能强大的“双刃剑”,在提供极致灵活性的同时也带来了风险。

✅ 优点

  1. 减少重复代码:可以编写通用的逻辑来处理不同类的字段(如通用的 ORM 框架)。
  2. 极高的灵活性:支持在不重新编译的情况下改变程序的行为。
  3. 突破封装限制:可以访问和修改通常不可见的私有成员(在特定调试场景下非常有用)。

❌ 缺点与风险

  • 🐢 性能开销:反射涉及动态解析,JVM 无法对其进行深度优化,调用速度明显慢于直接调用。避免在循环百万次的高频场景下使用。
  • ⚠ 内部暴露(安全性):反射通过 setAccessible(true) 打破了封装性。如果类内部字段名改变,反射代码将直接崩溃,导致代码难以维护且不可移植。
  • 🔒 安全限制:在受限环境(如 Java 9 模块化系统或特定安全容器)下,反射操作可能会被禁止。

5. 总结

  • 什么时候用:开发框架(Spring, MyBatis)、编写工具软件、实现插件化功能、自动化测试。
  • 什么时候不用:普通的业务逻辑开发。
  • 核心原则谨慎使用。如果可以通过多态或接口实现的功能,优先不要使用反射。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容