最近,当尝试从内部类访问外部类的父类中声明的受保护字段(由其他类加载器加载)时,遇到运行时错误java.lang.IllegalaccessError
的问题。简要地:
- 类
Parent
具有受保护的字段p
。 - 类
Outer
扩展了Parent
。 - 类
Inner
是在类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规范中的受保护类,但是由于我们使用内部类,因此可以正常工作。
因此,对于两种“不同的程序包”,我们有不同的行为。
- 声明为不同的包,由单个类加载器加载-确定。
- 声明为单个包,由不同的类加载器加载-不好。
有人可以对内部类如何访问父级字段进行解释,以及为什么在两种情况下内部类的工作方式不同吗?