訪問修飾符的真正理解

首先,必須明確Java中類成員的訪問修飾符(public、private、protect、默認或friendly等,C++也同理),並不能簡單的理解爲書上說的如“子類可以訪問”,具體因結合類的內存佈局圖來理解。例如一個父類有public a成員和protect b成員,在其子類的方法中訪問a時,要考慮子類的內存佈局能否看到a。    結合內存佈局圖就可以理解所謂“子類可以訪問父類的protect b成員”說的是指本子類繼承了父類的成員b,所以也具有b,當然就可以訪問了。對於private成員,子類不繼承,當然就沒有了。  對於public的東西,在任何地方都能找到,對於private和protect就看通過內存佈局能不能找到(即屬於自己的可以找到,不屬於自己的東西當然找不到了)。

【總之一句話,能不能訪問,就看在當前作用域下能不能找到。】


以下是原因分析:

在Core Java中有這樣一段話“在Object類中,clone方法被聲明爲protected,因此無法直接調用anObject.clone()。子類只能直接調用受保護的clone方法克隆它自己。爲此,必須重新定義clone方法,並將它聲明爲public,這樣才能讓所有的方法克隆對象”。但是不是所有的子類都可以訪問受保護的方法嗎?不是每個子類都是Object的之類嗎?下面就用例子來說明下protected訪問修飾符的問題。

在package1中創建SuperClass.java文件,裏面有一個protected方法,內容如下。

  1. package package1;  
  2.   
  3. public class SuperClass {  
  4.     protected void method(){  
  5.         System.out.println("This is a protected method in the super class .");  
  6.     }  
  7. }  
在同一個包中創建SubClass1.java文件,類SubClass1和類SubClass2均繼承自SuperClass,內容如下。

  1. package package1;  
  2.   
  3. public class SubClass1 extends SuperClass {  
  4.     public static void main(String[] args) {  
  5.         SuperClass sup = new SuperClass();  
  6.         SubClass1 sub1 = new SubClass1();  
  7.         SubClass2 sub2 = new SubClass2();  
  8.         sup.method();  //Compile OK   
  9.         sub1.method();  //Compile OK   
  10.         sub2.method();  //Compile OK   
  11.     }  
  12. }  
  13. class SubClass2 extends SuperClass{  
  14.       
  15. }  
編譯全部通過,不難理解,protected方法對同包中的類是可見的

如果在另一個包package2中創建SubClass1.java文件,內容與包package1中的SubClass1.java內容相同。

  1. package package2;  
  2.   
  3. import package1.SuperClass;  
  4.   
  5. public class SubClass1 extends SuperClass {  
  6.     public static void main(String[] args) {  
  7.         SubClass1 sub1 = new SubClass();  
  8.         SubClass2 sub2 = new SubClass2();  
  9.         Sub1.method();  //Compile OK   
  10.         sub2.method();  //Compile Error   
  11.     }  
  12.   
  13. }  
  14. class SubClass2 extends SuperClass{  
  15.       
  16. }  
這樣編譯器會在sub2.method()處報錯誤The method clone from the type SuperClass is not visiuable。這種情況下,調用protected方法的方法所屬的類是protected方法所屬類的子類,但是不在同一個包中。由此我們可以想到不能在一個子類中訪問另一個子類的protected方法,儘管這兩個子類繼承自同一個父類

如果我們在package2中的SubClass2中重寫SuperClass的method方法。

  1. package package2;  
  2.   
  3. import package1.SuperClass;  
  4.   
  5. public class SubClass extends SuperClass {  
  6.     public static void main(String[] args) {  
  7.         SubClass sub = new SubClass();  
  8.         SubClass2 sub2 = new SubClass2();  
  9.         sub.method();  //Compile OK   
  10.         sub2.method();  //Compile OK   
  11.     }  
  12.   
  13. }  
  14. class SubClass2 extends SuperClass{  
  15.     protected void method(){  
  16.         super.method();  
  17.     }  
  18. }  
這種情況跟第一種類似,protected方法可以被同一個包中的類訪問。當在SubClass2類中覆蓋method()方法時,SubClass2類和SubClass1類在同一個包下,所以此protected方法對SubClass1類可見。現在應該可以理解“爲此,必須重新定義clone方法,並將它聲明爲public,這樣才能讓所有的方法克隆對象”這句話了吧。

如果我們在一個類中調用父類對象的protected方法會怎麼樣?

在package1中創建父類SuperClass.java文件,裏面有一個protected方法,內容如下。

  1. package package1;  
  2.   
  3. public class SuperClass {  
  4.     protected void method(){  
  5.         System.out.println("This is a protected method in the super class .");  
  6.     }  
  7. }  

在另一個包package中創建子類SubClass.java文件,內容如下。

  1. package package2;  
  2.   
  3. import package1.SuperClass;  
  4.   
  5. public class SubClass extends SuperClass {  
  6.     public static void main(String[] args) {  
  7.         SuperClass sup = new SuperClass();  
  8.         SubClass sub = new SubClass();  
  9.         sup.method(); //Compile Error   
  10.         sub.method();  //Compile OK   
  11.     }  
  12.   
  13. }  

這裏我在SubClass繼承另一個包中的SuperClass,這個SuperClass中有一個protected方法method()。在SubClass類中調用SubClass類的實例sub的method()方法,編譯不會報錯。而同樣調用SuperClass類的實例sup的method()方法,編譯報錯!

protected方法不是可以被子類訪問的嗎?

從接觸Java開始就瞭解Java中訪問修飾符的權限可以用下面這個表格概括:

作用域
當前類
同包
子孫類(不同包)
其他
public
Y
Y Y Y
protected
Y
Y
Y
N
default
Y
Y
N
N
private
Y
N
N
N
default爲不寫訪問修飾符時。

現在必須明確的是:類SubClass確實是繼承了類SuperClass(包括它的method方法),所以在類SubClass中可以調用自己的method方法。但類SuperClass的protected方法對其不同包子類SubClass來說,是不可見的。

注意protected訪問修飾符的規則及其微妙。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章