Java 中關於protected的介紹

roc_guo發表於2021-07-10
導讀 protected的可見性在於基類的 protected 成員是包內可見的,並且對子類可見;若子類與基類不在同一包中,那麼在子類中,子類例項可以訪問其從基類繼承而來的protected方法,而不能訪問基類例項的protected方法。

Java 中關於protected的介紹Java 中關於protected的介紹

很多介紹Java語言的書籍(包括《Java程式設計思想》)都對protected介紹的比較的簡單,基本都是一句話,就是: 被 protected 修飾的成員對於本包和其子類可見。這種說法有點太過含糊,常常會對大家造成誤解。實際上,protected的可見性在於兩點:

  1. 基類的 protected 成員是包內可見的,並且對子類可見;
  2. 若子類與基類不在同一包中,那麼在子類中,子類例項可以訪問其從基類繼承而來的protected方法,而不能訪問基類例項的protected方法。

我們可以透過以下幾個關於protected方法可見性的例子來進一步掌握protected關鍵字。在碰到涉及protected成員的呼叫時,首先要確定出該protected成員來自何方,其可見性範圍是什麼,然後就可以判斷出當前用法是否可行了,看下面七個例子:

例項 1

package p1;
public class Father1 {
    protected void f() {}    // 父類Father1中的protected方法
}
 
package p1;
public class Son1 extends Father1 {}
 
package p11;
public class Son11 extends Father1{}
 
package p1;
public class Test1 {
    public static void main(String[] args) {
        Son1 son1 = new Son1();
        son1.f(); // Compile OK     ----(1)
        son1.clone(); // Compile Error     ----(2)
 
        Son11 son = new Son11();    
        son11.f(); // Compile OK     ----(3)
        son11.clone(); // Compile Error     ----(4)
    }
}

對於上面的示例,首先看(1)(3),其中的f()方法從類Father1繼承而來,其可見性是包p1及其子類Son1和Son11,而由於呼叫f()方法的類Test1所在的包也是p1,因此(1)(3)處編譯透過。其次看(2)(4),其中的clone()方法的可見性是java.lang包及其所有子類,對於語句"son1.clone();"和"son11.clone();",二者的clone()在類Son1、Son11中是可見的,但對Test1是不可見的,因此(2)(4)處編譯不透過。

例項 2

package p2;
class MyObject2 {
    protected Object clone() throws CloneNotSupportedException{
       return super.clone();
    }
}
 
package p22;
public class Test2 extends MyObject2 {
    public static void main(String args[]) {
       MyObject2 obj = new MyObject2();
       obj.clone(); // Compile Error         ----(1)
 
       Test2 tobj = new Test2();
       tobj.clone(); // Complie OK         ----(2)
    }
}

對於(1)而言,clone()方法來自於類MyObject2本身,因此其可見性為包p2及MyObject2的子類,雖然Test2是MyObject2的子類,但在Test2中不能訪問基類MyObject2的protected方法clone(),因此編譯不透過;對於(2)而言,由於在Test2中訪問的是其本身例項的從基類MyObject2繼承來的的clone(),因此編譯透過。

例項 3

package p3;
class MyObject3 extends Test3 {
}
 
package p33;
public class Test3 {
  public static void main(String args[]) {
    MyObject3 obj = new MyObject3();
    obj.clone();   // Compile OK     ------(1)
  }
}

對於(1)而言,clone()方法來自於類Test3,因此其可見性為包p33及其子類MyObject3,而(1)正是在p33的類Test3中呼叫,屬於同一包,編譯透過。

例項 4

package p4;
class MyObject4 extends Test4 {
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
}
 
package p44;
public class Test4 {
  public static void main(String args[]) {
    MyObject4 obj = new MyObject4();
    obj.clone(); // Compile Error      -----(1)
  }
}

對於(1)而言,clone()方法來自於類MyObject4,因此其可見性為包p4及其子類(此處沒有子類),而類Test4卻在包p44中,因此不滿足可見性,編譯不透過。

例項 5

package p5;
 
class MyObject5 {
    protected Object clone() throws CloneNotSupportedException{
       return super.clone();
    }
}
public class Test5 {
    public static void main(String[] args) throws CloneNotSupportedException {
       MyObject5 obj = new MyObject5();
       obj.clone(); // Compile OK        ----(1)
    }
}

對於(1)而言,clone()方法來自於類MyObject5,因此其可見性為包p5及其子類(此處沒有子類),而類Test5也在包p5中,因此滿足可見性,編譯透過。

例項 6

package p6;
 
class MyObject6 extends Test6{}
public class Test6 {
  public static void main(String[] args) {
    MyObject6 obj = new MyObject6();
    obj.clone();        // Compile OK   -------(1)
  }
}

對於(1)而言,clone()方法來自於類Test6,因此其可見性為包p6及其子類MyObject6,而類Test6也在包p6中,因此滿足可見性,編譯透過。

例項 7

package p7;
 
class MyObject7 extends Test7 {
    public static void main(String[] args) {
        Test7 test = new Test7();
        test.clone(); // Compile Error   ----- (1)
  }
}
 
public class Test7 {
}

對於(1)而言,clone()方法來自於類Object,因此該clone()方法可見性為包java.lang及其子類Test7,由於類MyObject7不在此範圍內,因此不滿足可見性,編譯不透過。

原文來自:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2780628/,如需轉載,請註明出處,否則將追究法律責任。

相關文章