簡體   English   中英

Java:對超類對象上的子類的受保護訪問限制

[英]Java : Protected access restriction for subclass on superclass object

我知道之前在這個論壇上有人問過這個問題,但我會再問一次,因為我沒有看到任何好的答案(到目前為止)。

它是這樣的:

package a;
public class A{
    protected int a;
}

package b;
public class B extends A{
}

package c;
public class C extends B{
    public void accessField(){
        A ancient = new A();
        ancient.a = 2;  //A - That wouldn't work.

        a = 2;   //B - That works.
    }

}

為什么 A) 條款不起作用? 子類 C 中對超類對象古代訪問的這種限制背后的原因是什么?
謝謝。

受保護的成員只能在同一個包之外通過繼承訪問——即在層次結構內。

因此,當您從不同的包創建 A 的另一個實例時,這不是繼承關系,因此會失敗。

與往常一樣,這在 JLS 6.6.2 中有介紹:

對象的受保護成員或構造函數可以從包外部訪問,在該包中僅由負責實現該對象的代碼聲明它。

實際上,您不需要兩級繼承,下面的代碼會導致相同的行為:

public class B extends A{
     public void accessField() {
        A ancient = new A();
        ancient.a = 2;  //A - That wouldn't work.

        a = 2;   //B - That works.
    }
}

a = 2工作的原因是JLS 6.2.2.1

設 C 是聲明受保護成員的類。 只允許在 C 的子類 S 的主體內訪問。

請注意,它沒有說直接子類,而只是說子類。 所以a = 2B類或C類中工作。

另一方面, ancient.a = 2; 包含在同一部分的下一個要點中:

如果訪問是通過限定名稱 Q.Id 進行的,其中 Q 是 ExpressionName,那么當且僅當表達式 Q 的類型是 S 或 S 的子類時才允許訪問。

在你的情況, Q.Idancient.a =>那只如果訪問的類型ancientB或子類B 例如,這將編譯:

public class B extends A{
     public void accessField() {
        C ancient = new C();
        ancient.a = 2;  //A - That wouldn't work.
     }
}

引自 The Java Programming Language 3 ed 一書。 作者:Gosling 等人 - 第 81 頁 3.5

“受保護的真正含義” - .. 除了可以在類本身中訪問以及在同一個包中進行編碼之外,還可以通過與類至少具有相同類型的對象引用從類訪問受保護成員 - 即類的類型或其子類之一的引用

引用JLS 6.6.2

對象的受保護成員或構造函數可以從包外部訪問,在該包中僅由負責實現該對象的代碼聲明它。

當你說,

A ancient = new A();
ancient.a = 2;

您沒有從古代(一個對象)繼承任何東西,因此不對其實現負責。 通過使C 擴展 A ,您已經從不同的 A 對象繼承了 'a',因此下面的語句有效。

a = 2;

如果,

ancient.a = 2;

有效,那么公共和私有訪問說明符之間沒有區別。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM