不同包子类通过反射访问自身protected成员变量触发IllegalAccessException
问题原因与解决方案
这个问题的核心其实是Java中protected访问权限的规则,以及反射对这些规则的严格遵循——哪怕是通过父类的方法来访问子类的protected成员,跨包的时候也会触发权限检查,这就是你遇到IllegalAccessException的原因。
为什么B正常,C报错?
我们先理清楚protected权限的两个核心访问边界:
- 同一个包内的所有类,都可以访问彼此的protected成员;
- 子类中可以访问自身实例的protected成员(包括从父类继承的,或者自己定义的),但父类没有权限直接访问跨包子类的protected成员——哪怕是通过子类实例来访问也不行。
对应你的场景:
- B和A在同一个包下,所以A的
reflect方法不管是直接访问还是反射访问B的protected字段,都符合权限规则,自然不会报错; - C和A分属不同包,A作为C的父类,在A的方法里通过
this(也就是C的实例)反射访问C的protected字段时,Java的访问控制机制会判定A没有权限——protected的设计是让子类能访问父类的成员,而不是反过来让父类访问跨包子类的成员。
怎么解决这个异常?
要绕过这个权限检查,你只需要在反射获取到字段后,调用setAccessible(true)方法关闭该字段的访问权限校验即可。修改后的reflect方法大概是这样:
public void reflect(String fieldName) throws NoSuchFieldException, IllegalAccessException { Field field = this.getClass().getDeclaredField(fieldName); field.setAccessible(true); // 关键:关闭访问权限检查 Object value = field.get(this); // 后续逻辑 }
⚠️ 注意:setAccessible(true)会破坏Java的封装性,建议只在确实有必要的场景下使用,比如框架开发、反射工具类等场景。
内容的提问来源于stack exchange,提问作者Bluescreen
相关产品推荐
相关产品推荐

