訪問控制符聲明爲protected
的成員可以被同一包或者子類訪問, 默認訪問控制符的成員可以被同一個包訪問.
更詳細的說, protected的規則如下:
- 包內可見,並對子類可見.
- 若子類和父類不在同一個包, 子類中子類實例可以訪問從父類繼承來的protected方法, 而不能訪問父類實例的protected方法
引申: 若和父類不在同一個包中, 子類不能訪問其他子類的父類protected方法. 也就是p227說的, 子類只能調用受保護的clone方法來克隆自己的對象的由來.
舉例:
//Duck1.java
package playground;
public class Duck1 {
public static void main(String[] args) {
Duck1 d = new Duck1();
d.testSelfClone();
d.testOtherSubclassClone();
d.testOtherSubclassWithPublicClone();
}
public void testSelfClone() {
clone(); // 可以, 從父類繼承來的
}
public void testOtherSubclassClone() {
Duck2 d2 = new Duck2();
d2.clone(); // 是要報錯的, 不能在子類中調用其他子類的父類protected方法.
}
public void testOtherSubclassWithPublicClone() {
Duck3 d3 = new Duck3();
d3.clone(); // 可以, 該類開放了public
}
}
//Duck2.java
package playground;
public class Duck2 { }
//Duck3.java
package playground;
public class Duck3 {
public Duck3 clone() throws CloneNotSupportedException {
return (Duck3) super.clone();
}
}
但是如果子類和父類在同一個包中, 事情又不一樣了. 因爲在同一個包中, 父類的protected方法是可見的.因此, 子類可以訪問別的子類的父類protected方法.
//Bird.java
package playground;
public class Bird {
protected void pFunc() {
System.out.println("IN Bird.pFunc.");
}
}
//Duck1.java
package playground;
public class Duck1 extends Bird{
public static void main(String[] args) {
Duck1 d = new Duck1();
d.testSelfpFunc();
d.testOtherSubclasspFunc();
d.testOtherSubclassWithPublicpFunc();
}
public void testSelfpFunc() {
pFunc(); // 可以, 從父類繼承來的
}
public void testOtherSubclasspFunc() {
Duck2 d2 = new Duck2();
d2.pFunc(); // 可以, 因爲在同一個包
}
public void testOtherSubclassWithPublicpFunc() {
Duck3 d3 = new Duck3();
d3.pFunc();
}
}
//Duck2.java
package playground;
public class Duck2 extends Bird{ }
//Duck3.java
package playground;
public class Duck3 extends Bird { }