2017-10-20 103 views
-1

考慮下面的代碼:爲什麼受保護訪問的Java規則是這樣的?

public class Sup { 
    protected void method(){} 
} 

//another package 
class Sub extends Sup { 
    public static void main(String[] args) { 
     new Sub().method(); 
     new Sup().method(); // does not compile 
    } 
} 

我的問題是:爲什麼它這樣的方式設計的第二個呼叫無法編譯?

+0

什麼是錯誤信息? –

+0

爲什麼你認爲它*應該*編譯? –

+0

OP不認爲它應該編譯。他也沒有要求程序不編譯的原因。 OP想知道Java中這種設計選擇的原因。 – Zabuza

回答

1

protected主要用於效用輔助方法一類的內部。它們並不意味着可以從外部訪問,如private方法。

然而,延伸類可能需要訪問這些方法或甚至修改它們。所以基本上它是就像private,其存在的權利應該是明確的,但是你想讓擴展類有機會也可以訪問它。

這種情況經常發生,他們決定在該語言中包含protected。如果您有其他願望或設計建議,請隨時分享。


這裏是經常引用overview table

  | Class | Package | Subclass | Subclass | World 
      |  |   |(same pkg)|(diff pkg)| 
————————————+———————+—————————+——————————+——————————+———————— 
public  | + | + | +  |  + | +  
————————————+———————+—————————+——————————+——————————+———————— 
protected | + | + | +  |  + |   
————————————+———————+—————————+——————————+——————————+———————— 
no modifier | + | + | +  |   |  
————————————+———————+—————————+——————————+——————————+———————— 
private  | + |   |   |   |  

+ : accessible 
blank : not accessible 

想想,你提供一些abstract基類,像AbstractMap的例子。它可以有一種重新安排內部事物的方法。

您可以製作方法private,但您也可以製作protected,因爲擴展類可以通過覆蓋來更改重新排列過程。如果擴展類由於其特定的結構,可以使用額外的知識來創建更高效​​的方法,這可能會很有用。

2

的JLS說什麼

的JLS的相關部分表示如下:

令C是其中一個受保護的成員被聲明的類。訪問只內C.

另外的一個子類S的體允許的,並且,當ID表示一個實例字段或實例方法,則:

  • 如果接入是由合格的名稱Q. Id,其中Q是表達式名稱,則當且僅當表達式Q的類型是S或S的子類時允許訪問。

  • 如果訪問是通過字段訪問表達式E.Id進行的,其中E是主表達式,或者通過方法調用表達式E.Id(...)(其中E是主表達式),則只有當ty E的pe是S或S的一個子類。

Source

向供應它的方法中的呼叫沒有通過第二個規則,因爲它是一個超類,而不是一個子類。

對Sub的調用是相同的類,所以它通過了規則。

爲什麼說這

protected成員打算從子類的內部代碼中使用,所以能夠從不同的對象的子類訪問它將使你影響對象的狀態,你不應該能夠。