java - Java:从内部类访问受保护的字段
问题描述
java.lang.IllegalAccessError
最近,当我尝试从内部类访问由不同类加载器加载的外部父类中声明的受保护字段时,我遇到了一个运行时错误的问题。简要地:
- 类
Parent
有受保护的领域p
。 - 类
Outer
扩展Parent
。 - Class
Inner
是定义在 class 中的内部类Outer
。 - 里面
Inner
有一个代码:Outer.this.p
. - 所有类都在同一个包中声明。
通常它被编译并运行良好,直到Parent
类Outer
被不同的类加载器加载。在这种情况下,我们java.lang.IllegalAccessError
在尝试Outer.this.p
从Inner
. 我发现了一个旧的错误报告(这似乎是一个功能)描述了这种行为:
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6258289
但分辨率听起来与我矛盾:
关键是,在失败的情况下,内部类不在同一个包中(并且不是 ConcreteCommand/AbstractCommand 的子类)。这只是违反了受保护类的 Java 规范。
听起来是正确的。但是,如果我们在不同的包中声明Parent
和Outer
类但使用单个类加载器加载(只需创建没有任何 jar 加载的示例控制台应用程序),我们不会收到任何错误。所以从技术上讲,它违反了受保护类的 Java 规范,但由于我们使用内部类,它可以工作。
因此,对于两种“不同包”的情况,我们有不同的行为。
- 在不同的包中声明,由单个类加载器加载 - 好的。
- 在单个包中声明,由不同的类加载器加载 - 不好。
有人可以清楚地解释内部类如何访问父字段以及为什么它在两种情况下的工作方式不同吗?
解决方案
- 相同的类加载器似乎正在工作
- 我问对了吗?
- 您是否有任何单元测试用例来重现您的问题?
家长班
package p1;
public class Parent {
protected String p = "Value from Parent";
public void test() {
System.out.println(p);
}
}
外层
package p1;
public class Outer extends Parent {
class Inner {
public void test() {
Outer.this.p = "Value set from Inner";
System.out.println(Outer.this.p);
}
}
public void test() {
new Inner().test();
}
}
主班
package p1;
public class Main {
public static void main(String[] args) {
Parent p = new Parent();
p.test();
p = new Outer();
p.test();
}
}
输出
Value from Parent
Value set from Inner
推荐阅读
- javascript - 下一篇 JS 如何将状态传递给 getStaticProps
- reactjs - 分页问题,有一次我迷路了
- reactjs - React Router:通过浏览器地址栏导航到路由时状态为空
- java - Netty 如何完全忽略来自未知 IP 的 TCP/UDP 数据包
- pandas - 价值变化的概率
- c# - 如何为 C# 下载 System.IO.Ports
- algorithm - 获取 k 个整数,使得列表之和的比率最大
- python - discord.py 使用不和谐组件的帮助命令
- xml - 如何在 Oracle 中解析 XML
- c++ - 是否可以通过动态编程解决 HackerRank 的不可分割子集?