class \ have access to | private elements |
default elements (no modifier) |
protected elements |
public elements |
---|---|---|---|---|
own class (Base ) |
yes | yes | yes | yes |
subclass - same package (SubA ) |
no | yes | yes | yes |
class - same package (AnotherA ) |
no | yes | yes | yes |
subclass - another package (SubB ) |
no | no | yes/no* | yes |
class - another package (AnotherB ) |
no | no | no | yes |
*与基类不在同一个包中的子类,只能访问自身从基类继承而来的受保护成员,而不能访问基类实例本身的受保护成员。
举个例子说明:
package package1;
public Class Base{
protected int i=5;}
package package2;
public Class SubB extends Base{
public static void main(String arg[]){
SubB subb = new SubB();
subb.i=6;
System.out.println(sub.i);// 正确 与基类不在同一个包中的子类,可以访问自身从基类继承而来的受保护成员
Base base=new Base();
base.i=6;
System.out.println(base.i);//错误 与基类不在同一个包中的子类,不能访问基类实例本身的受保护成员
}
}
其实default(friendly)与protected的区别就在于,与基类不在同一个包中的子类可以继承基类的protected元素,却无法继承default元素。看到很多人说
public | protected | default | private | |
同类 | T | T | T | T |
同包 | T | T | T | |
子类(不同包) | T | T | ||
不同包中无继承关系的类 | T |
中继承,这唯一能够访问的成员就是原来那个包中的public成员”,可见不同包中的子类是不能访问基类的protected成员的,只能继承。这是最容易混淆的地方。
其他如private和public我想大家应该清楚,我就不复述了。
参考资料(英文):http://bmanolov.free.fr/javaprotection.php#subb
Code Example
All lines with not accessible fields are commented.
package packageA;
public class Base {
public String publicStr = "publicString";
protected String protectedStr = "protectedString";
String defaultStr = "defaultString";
private String privateStr = "privateString";
public void print() {
System.out.println("packageA.Base has access to");
System.out.println(" " + publicStr);
System.out.println(" " + protectedStr);
System.out.println(" " + defaultStr);
System.out.println(" " + privateStr);
Base b = new Base(); // -- other Base instance
System.out.println(" b." + b.publicStr);
System.out.println(" b." + b.protectedStr);
System.out.println(" b." + b.defaultStr);
System.out.println(" b." + b.privateStr);
}
}
--------------------------------------------------------------------------------
package packageA;
public class SubA extends Base {
public void print() {
System.out.println("packageA.SubA has access to");
System.out.println(" " + publicStr + " (inherited from Base)");
System.out.println(" " + protectedStr + " (inherited from Base)");
System.out.println(" " + defaultStr + " (inherited from Base)");
// -- not accessible - private elements are even not inherited
// System.out.println(privateStr);
Base b = new Base(); // -- other Base instance
System.out.println(" b." + b.publicStr);
System.out.println(" b." + b.protectedStr);
System.out.println(" b." + b.defaultStr);
// -- not accessible
// System.out.println(b.privateStr);
}
}
--------------------------------------------------------------------------------
package packageA;
public class AnotherA {
public void print() {
System.out.println("packageA.AnotherA has access to");
Base b = new Base();
System.out.println(" b." + b.publicStr);
System.out.println(" b." + b.protectedStr);
System.out.println(" b." + b.defaultStr);
// System.out.println(b.privateStr);
}
}
--------------------------------------------------------------------------------
package packageB;
import packageA.Base;
public class SubB extends Base {
public void print() {
System.out.println("packageB.SubB has access to");
System.out.println(" " + publicStr + " (inherited from Base)");
// -- protectedStr is inherited element -> accessible
System.out.println(" " + protectedStr + " (inherited from Base)");
// -- not accessible
// System.out.println(defaultStr);
// System.out.println(privateStr);
Base b = new Base(); // -- other Base instance
System.out.println(" b." + b.publicStr);
// -- protected element, which belongs to other object -> not accessible
// System.out.println(b.protectedStr);
// -- not accessible
// System.out.println(b.defaultStr);
// System.out.println(b.privateStr);
}
}
--------------------------------------------------------------------------------
package packageB;
import packageA.Base;
public class AnotherB {
public void print() {
System.out.println("packageB.AnotherB has access to");
Base b = new Base();
System.out.println(" b." + b.publicStr);
// -- not accessible
// System.out.println(b.protectedStr);
// System.out.println(b.defaultStr);
// System.out.println(b.privateStr);
}
}
--------------------------------------------------------------------------------
import packageA.*;
import packageB.*;
// -- testing class
public class TestProtection {
public static void main(String[] args) {
// -- all classes are public, so class TestProtection
// -- has access to all of them
new Base().print();
new SubA().print();
new AnotherA().print();
new SubB().print();
new AnotherB().print();
}
}