457. Java 反射 - 深度访问

文章目录

  • 457. Java 反射 - 深度访问
    • 1. 深度访问示例:修改私有字段
    • 2. 深度反射与 Java 模块系统
    • 3. 总结

457. Java 反射 - 深度访问

到目前为止,我们看到的都是安全的反射操作

  • 获取公共方法
  • 调用静态方法
  • 调用接口方法

这些方法没有真正突破 Java 的访问控制,唯一“危险”的地方是编译器无法保证方法存在或可访问。

现在,我们要尝试深入镜子,操作私有字段和不可见的成员。


1. 深度访问示例:修改私有字段

假设我们有一个简单的Person类:

publicclassPerson{privatefinalStringname;privatefinalintage;publicPerson(Stringname,intage){this.name=name;this.age=age;}@OverridepublicStringtoString(){returnname+" ("+age+")";}}

我们想通过 Reflection修改私有且final的字段

importjava.lang.reflect.Field;publicclassFountainOfYouth{publicstaticvoidmain(String[]args)throwsReflectiveOperationException{Personperson=newPerson("Heinz Kabutz",51);System.out.println(person);// 获取私有字段FieldageField=Person.class.getDeclaredField("age");ageField.setAccessible(true);// ⚠ 开启深度反射// 修改字段值intage=(int)ageField.get(person);age*=0.9;// 年轻 10%ageField.set(person,age);System.out.println(person);}}

输出示例

HeinzKabutz(51)HeinzKabutz(45)

说明

  • 虽然age字段是private final,但通过深度反射,我们仍然可以修改它
  • 如果Personrecord,则无法通过深度反射修改字段

2. 深度反射与 Java 模块系统

在 Java 9 之后,引入了模块系统(Module System):

  • 深度反射只有在模块开放的情况下才可用
  • 理想情况下,应请求模块作者开放包给你的模块
  • 否则,你可能需要通过--add-opens命令行参数强行打开包(不推荐)

风险提示

  • 深度反射可能破坏封装
  • 模块升级或字段更改可能导致反射代码崩溃
  • 仅在绝对必要时使用

3. 总结

  1. 浅层反射:访问公共方法、调用静态方法,安全、常用
  2. 深度反射:访问私有、final字段和方法,危险且不推荐
  3. 模块与安全
    • 深度反射受模块访问限制
    • 不要随意依赖模块内部实现细节