对于private、public和缺省默认的权限修饰符很清楚明白:
private修饰的属性或方法——仅对本类可见
public修饰的属性或方法——对外部都可见
缺省默认的——仅对本包可见
而对于用protected修饰属性或方法的某个类,关系很复杂微妙,大致有以下几种情况:
(1)在本包内的其它类中,可以通过父类的对象来访问protected修饰的属性或方法。
(2)在包外的子类中,不能用父类的对象来访问protected修饰的属性或方法,包外的其它类中更不行。
(3)在包外的子类1中,只能通过子类1对象访问自己继承来的protected修饰的属性或方法。
(4)在包外的子类1中,不能通过子类2的对象访问子类2继承来的protected修饰的属性或方法。
(5)在包外的子类中,可以通过super来访问父类中protected修饰的属性或方法。
(6)在包外其它类中,不能通过子类对象访问子类继承来的protected修饰的属性或方法。
(7)在本包内的其它类中,可以通过包外子类的对象来访问继承来的protected修饰的属性或方法。
(8)对于protected修饰的static静态变量,在子类中可以直接访问。
父类包:
package protected1;
public class ProtectedFather {
protected String name = "Jack";
protected void print(){
System.out.println("protected修饰print():"+"name = "+this.name);
}
}
package protected1;
import protected2.ProtectedSub1;
import protected2.ProtectedSub2;
public class Other1 {
/*在本包内的其它类中,可以通过父类的对象来访问protected修饰的属性或方法。*/
public void test0(){
ProtectedFather protectedFather = new ProtectedFather();
protectedFather.name = "Tom";
protectedFather.print();
}
/*在本包内的其它类中,可以通过包外子类的对象来访问继承来的protected修饰的属性或方法。*/
public void test1(){
ProtectedSub1 protectedSub1 = new ProtectedSub1();
protectedSub1.name = "Tom";
protectedSub1.print();
}
/*在本包内的其它类中,可以通过包外子类的对象来访问继承来的protected修饰的属性或方法。*/
public void test2(){
ProtectedSub2 protectedSub2 = new ProtectedSub2();
protectedSub2.name = "Tim";
protectedSub2.print();
}
}
子类包:
package protected2;
import protected1.ProtectedFather;
public class ProtectedSub1 extends ProtectedFather {
/*在包外的子类中,不能用父类的对象来访问protected修饰的属性或方法,包外的其它类中更不行。*/
public void test0(){
ProtectedFather protectedFather = new ProtectedFather();
protectedFather.name = "Lily"; //不行
protectedFather.print(); //不行
}
/*在包外的子类1中,只能通过子类1对象访问子类1继承来的protected修饰的属性或方法。*/
public void test1(){
ProtectedSub1 protectedSub1 = new ProtectedSub1();
protectedSub1.name = "Rose";
protectedSub1.print();
}
/*在包外的子类1中,不能通过子类2的对象访问子类2继承来的protected修饰的属性或方法。*/
public void test2(){
ProtectedSub2 protectedSub2 = new ProtectedSub2();
protectedSub2.name = "Tim"; //不行
protectedSub2.print(); //不行
}
/*在包外的子类中,可以通过super来访问父类中protected修饰的属性或方法。*/
public void test3(){
super.name = "Jerry";
super.print();
}
}
package protected2;
import protected1.ProtectedFather;
public class ProtectedSub2 extends ProtectedFather {
/*在包外的子类中,不能用父类的对象来访问protected修饰的属性或方法,包外的其它类中更不行。*/
public void test0(){
ProtectedFather protectedFather = new ProtectedFather();
protectedFather.name = "Lily"; //不行
protectedFather.print(); //不行
}
/*在包外的子类2中,不能通过子类1的对象访问子类1继承来的protected修饰的属性或方法。*/
public void test1(){
ProtectedSub1 protectedSub1 = new ProtectedSub1();
protectedSub1.name = "Rose"; //不行
protectedSub1.print(); //不行
}
/*在包外的子类2中,只能通过子类2对象访问子类2继承来的protected修饰的属性或方法。*/
public void test2(){
ProtectedSub2 protectedSub2 = new ProtectedSub2();
protectedSub2.name = "Tim";
protectedSub2.print();
}
/*在包外的子类中,可以通过super来访问父类中protected修饰的属性或方法。*/
public void test3(){
super.name = "Jerry";
super.print();
}
}
package protected2;
import protected1.ProtectedFather;
public class Other2 {
/*在包外的子类中,不能用父类的对象来访问protected修饰的属性或方法,包外的其它类中更不行。*/
public void test0(){
ProtectedFather protectedFather = new ProtectedFather();
protectedFather.name = "Lily"; //不行
protectedFather.print(); //不行
}
/*在包外其它类中,不能通过子类对象访问子类继承来的protected修饰的属性或方法。*/
public void test1(){
ProtectedSub1 protectedSub1 = new ProtectedSub1();
protectedSub1.name = "Rose"; //不行
protectedSub1.print(); //不行
}
/*在包外其它类中,不能通过子类对象访问子类继承来的protected修饰的属性或方法。*/
public void test2(){
ProtectedSub2 protectedSub2 = new ProtectedSub2();
protectedSub2.name = "Tim"; //不行
protectedSub2.print(); //不行
}
}
以上代码之间的关系,见下图:
总结:
简言之,在Java中,protected修饰的属性或方法只能由同一个包中的类访问,以及包外子类访问(包外子类只能通过super.属性或super.方法访问)。