[英]Java: accessing protected fields from inner class
Recently I've faced a problem getting a runtime error java.lang.IllegalAccessError
when trying to access from inner class a protected field declared in outer's parent class that was loaded by a different class loader. 簡要地:
Parent
具有受保護的字段p
。Outer
擴展Parent
。Inner
是在 class Outer
中定義的內部 class 。Inner
class 里面有一個代碼: Outer.this.p
。 通常它會編譯並運行良好,直到Parent
和Outer
class 由不同的 class 加載程序加載。 在這種情況下,我們在嘗試從Inner
訪問Outer.this.p
時得到java.lang.IllegalAccessError
。 我發現了一個舊的錯誤報告(這似乎是一個功能)描述了這種行為:
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6258289
但分辨率聽起來與我矛盾:
關鍵是,在失敗的情況下,內部 class 不在同一個 package(並且不是 ConcreteCommand/AbstractCommand 的子類)中。 這完全違反了受保護類的 Java 規范。
聽起來是正確的。 但是,如果我們在不同的包中聲明Parent
和Outer
類,但使用單個 class 加載器加載(只需創建沒有任何 jar 加載的示例控制台應用程序),我們不會收到任何錯誤。 所以從技術上講,它違反了 Java 規范的受保護類,但由於我們使用內部 class 它可以工作。
因此,對於兩種“不同包”的情況,我們有不同的行為。
有人可以清楚地解釋內部 class 如何訪問父字段以及為什么它在兩種情況下的工作方式不同?
父 Class
package p1;
public class Parent {
protected String p = "Value from Parent";
public void test() {
System.out.println(p);
}
}
外 Class
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();
}
}
主Class
package p1;
public class Main {
public static void main(String[] args) {
Parent p = new Parent();
p.test();
p = new Outer();
p.test();
}
}
Output
Value from Parent
Value set from Inner
在不同的包中聲明,由單個 class 加載程序加載 - OK
“受保護”訪問考慮到類之間的父子關系,並允許子類訪問父類的“受保護”成員,即使它們位於不同的包中。 所以,我認為這符合預期。
在單個 package 中聲明,由不同的 class 加載器加載 - 不正常
這與運行時包有關。 檢查這個。 現在我們知道,由於通過兩個不同的 class 加載程序加載,Parent 與 Outer 和 Inner 處於不同的運行時 package 中。 同時,我們還必須記住,Outer 是 Parent 的“孩子”,而 Inner 不是。 Inner 與 Parent 沒有“Is-a”關系。
綜上所述:由於 Parent 位於不同的運行時 package 中,因此 Inner 無法訪問 Parent 的“受保護”成員,因為 Inner 不是 Parent 的孩子。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.