2013-04-05 62 views
0
package p1; 

public class MyClass1 { 

     protected static String str = "ss1"; 

    } 

package p2; 

import p1.MyClass1; 

public class MyClass2 extends MyClass1 { 

    public static void test(){ 

     MyClass1 mc1 = new MyClass1(); 

     System.out.println(mc1.str); 

     } 

} 

據我所知,如果字符串被聲明爲受保護的,因爲它從另一個包中不可見,則print語句將不起作用。但是,爲什麼當聲明爲靜態保護時它工作?受保護字段的可見性

回答

3

靜態修飾符與可見性無關,所以沒有什麼會改變。不能訪問受保護的成員(即字段,方法)來自不同的包,無論它是否是靜態的。

但在你的情況下,MyClass2擴展了MyClass1。您可以從超類訪問受保護的成員。仍然,靜態與此無關。

編輯:

那麼,這是因爲涉及兩個不同的東西非常有趣的案例: 1)訪問從子類保護成員在不同的包, 2)語法技巧允許您訪問靜態(類)成員喜歡實例成員。

我會延長你的例子來說明什麼是真正的你在這個代碼做:

package p1; 

public class MyClass1 { 

    protected String protectedString = "example"; 

    protected static String protectedStaticString = "example"; 

} 

package p2; 

import p1.MyClass1; 

public class MyClass2 extends MyClass1 { 

    public void testProtected() { 

     MyClass1 otherMC1 = new MyClass1(); 
     MyClass2 otherMC2 = new MyClass2(); 

     String testProtected; 

     testProtected = this.protectedString; // OK, protectedString is inherited, so it's instance member of this class 
     testProtected = super.protectedString; // OK, it's also instance member of superclass 

     testProtected = otherMC1.protectedString; // ERROR. You can't access protected members of other instance of superclass 
     testProtected = otherMC2.protectedString; // OK. As it's inherited member of MyClass2, you can access it if it belongs to other instance of your class 

    } 

    public void testProtectedStatic() { 

     MyClass1 otherMC1 = new MyClass1(); 
     MyClass2 otherMC2 = new MyClass2(); 

     String testProtectedStatic; 

     testProtectedStatic = this.protectedStaticString; // OK - syntax trick 
     testProtectedStatic = super.protectedStaticString; // OK - syntax trick 

     testProtectedStatic = otherMC1.protectedStaticString; // OK - syntax trick 
     testProtectedStatic = otherMC2.protectedStaticString; // OK - syntax trick 

     testProtectedStatic = MyClass1.protectedStaticString; // OK - you can access protected static members from superclass 
     testProtectedStatic = MyClass2.protectedStaticString; // OK - this also static member of your class 
    } 

} 

現在,什麼是「語法絕招」。編譯器允許您訪問靜態成員,如他們是實例成員:

MyClass mc = new MyClass(); 
Object o = mc.STATIC_FIELD; 

但是,將實際編譯成字節碼:

MyClass mc = new MyClass(); 
Object o = MyClass.STATIC_FIELD; 

訪問靜態成員以這種方式被認爲是不好的做法,因爲這是誤導。您應該始終以靜態方式訪問靜態成員,以避免在閱讀代碼時出現混淆。

這是什麼在你的情況。有靜態字段以非靜態方式訪問,所以它看起來像實例字段。當您刪除靜態修飾符時,它成爲實例成員。訪問該字段的方式發生了變化,但您沒有注意到,因爲您的語法爲object.staticField

+0

的確如此,我剛剛注意到了這一點,並且我編輯了答案。 – 2013-04-05 19:53:29

+0

您可以通過繼承從不同的包進行訪問。 – elias 2013-04-05 19:54:01

+0

感謝您的回答。但是,如果String str只受保護,爲什麼它不起作用呢?我仍然從子類訪問它。 – user2250448 2013-04-05 22:16:35

0

它與靜態或沒有關係。您可以訪問該成員,因爲MyClass2擴展了MyClass1

1

如前所述,靜態與可見性無關。

在你的情況,「STR」被標記爲受保護的,這意味着2種類型的類可以看到: - 類在同一個包 - 擴展MyClass1的

你的代碼的工作,因爲MyClass2擴展類MyClass1的。

0

這是一個有趣的規則:您可以訪問在超類中定義的受保護的實例變量,但不能使用私有實例變量訪問該類的子類中的私有實例變量。例如

public class Super { 
    private String str; 
} 

public class Sub extends Super { 
    public void getStr(){ 
     return str; // not allowed. 
    } 
} 

然而,如果使用了以下內容,然後這是允許的:

public class Super { 
    protected String str; 
} 

public class Sub extends Super { 
    public void getStr(){ 
     return str; // allowed. 
    } 
} 
0
  • public意味着它的所有類可見。
  • protected表示它對包和所有子類可見。
  • (無修飾符)表示僅對包裝可見。
  • private意味着它只在其自己的類中可見。

請參閱Controlling Access to Members of a Class瞭解更多信息。