访问控制符声明为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 { }