Java基础知识详解: protected修饰符
@author: Tobin
Java初学者,试图用最简单的大白话让自己搞懂一些知识点。
修饰符modifiers介绍
学习Java不可避免地接触到一些基本的修饰符。
修饰符决定了类成员的访问权限,是否能够被其它类所访问。
- private: 只能被基类访问
- 无修饰符: 被基类,子类和同package的类访问
- protected: 在无修饰符的基础上,加了与基类不同包,但是是子类的访问权限,这个访问权限只在子类访问自身的实例时才有,超类的实例还是不能访问的
- public: 全都可以访问
下面这个很好地展现了权限的逐层增加。
protected修饰符详解
《Java编程思想》对protected的介绍是:被protected修饰的成员对于本包和其子类可见。看了上面的图,我们知道子类可见的意思是不同包的子类也是可见的。总结一下就是:
- 基类的protected成员是包内可见的
- 当不在同一个包,但是是其子类也是可以访问protected的成员的。但是有个前提,就是子类只能访问其继承来的protected成员,如果是在子类中初始化一个超类的实例,这个实例是无法访问protected的成员的。
概念比较抽象,用形象的语言来说。
包就相当于一个家族。不同包有可能有继承的分支,也有可能毫无关系。类内的成员就相当于资源。 - private: 私有资源,只能自己使用
- default: 家族,我自己,我子孙可以用
- protected: 我可以开放,但是只给自己家族的但是嫁到或者入赘其它家族的后代使用
- public: 谁都可以用,水资源
参考几个例子,分析下。
(1)示例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)
}
}
- f方法是超类Father1的,son1和son11虽然是定义不同的包,但是它们的都是Father1的子类,所以都可以访问f方法。此外Test1也在p1包里,所以1和3编译通过。
- son1和son11的clone()方法都是来自于Father1,但是和f的区别在于,Father的clone()还来自于java.lang.Object,Test1也是Object的子类,这只是说明它可以访问自己继承的clone()方法,即使其它分支继承了相同的方法,它也是不可以访问的。想象一下,家族给其它分支都分配一些资源,即使是相同的,我也不该有权限去访问其它分支的资源。
(2)示例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)
}
}
- Test2继承了MyObject2,clone()方法来源于MyObject2,Test2可以建立自身实例,然后访问clone()方法,2通过
- 但是作为子类,Test2建立超类实例,直接去访问超类的protected方法是不可以的
- 想一下,家族已经给我分支资源了,我还要直接向家族拿资源,不该有这个权限
(3)示例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)
}
}
- MyObject3继承Test3,两个不在一个包内。Test3作为超类,建立了子类的一个实例,访问子类继承的来自于它的方法,当然它的clone()方法,也是继承自java.lang.Object,这个不管,继承自我的,我是有权限访问的
- 想象一下,家族给分支资源了,家族是有权限直接访问我给出的资源的
(4)示例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)
}
}
- 和示例3的区别在于,此时的clone()方法是子类自身的方法了,来源于MyObject4本身,作为超类是没有权限访问子类的protected成员的
- 想象一下,分支建立自己的受保护资源,家族没有权限直接访问的
(5)示例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)
}
}
- 现在属于同一个包,Test5可以直接访问Myobject5的protected成员
- 想象一下,同一个家族的资源共享
(6)示例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
- 同一个家族的资源共享
(7)示例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 {}
- 超类Test7的方法来自于java.lang.Object,只有java.lang这个包和对应继承了这个clone()方法的Test7才能访问。说白了,方法还是一个方法,但是被不同的子类继承了,就不再是同样的方法了。
- 看起来是一个家族的,实际上资源是超类从其它家族得到的。其它家族对该资源做了限制,所以不能整个家族都能使用。其次,子类只能访问自身实例的protected资源,没有权限访问超类实例的protected资源。两个条件都不满足。
其它修饰符
static
final
abstract
见我Java基础知识系列的其它文章。
总结
protected成员,在相同package下,对其它类开放,不同package下,对继承了该类的子类开放(有条件)。其它包的子类没有权限直接创建超类的实例,然后访问超类的protected成员。除了认清楚protected属性,更重要的是要辨别来源,来源决定package是哪个,这是决定访问权限的基础。
参考文章
https://blog.csdn.net/ciawow/article/details/8262609。
https://blog.csdn.net/justloveyou_/article/details/61672133