Java protected Keyword Detailed Explanation
Category Programming Technology
Many books introducing the Java language (including "Thinking in Java") provide a simple explanation of the protected
keyword, basically stating that: Members decorated with protected
are visible to the package and its subclasses. This statement is too vague and often causes misunderstandings. In fact, the visibility of protected
involves two points:
- Protected members of a base class are visible within the package and to its subclasses.
- If the subclass is not in the same package as the base class, within the subclass, the subclass instance can access the protected methods inherited from the base class, but cannot access the protected methods of the base class instance.
We can further understand the protected
keyword by examining several examples regarding the visibility of protected methods. When encountering calls involving protected members, first determine where the protected member comes from and what its visibility scope is, and then you can judge whether the current usage is feasible. Consider the following seven examples:
Example 1
package p1;
public class Father1 {
protected void f() {} // protected method in parent class Father1
}
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)
}
}
For the above example, first look at (1)(3), where the f()
method is inherited from class Father1
, and its visibility is package p1
and its subclasses Son1
and Son11
. Since the class Test1
calling f()
is also in package p1
, the compilation passes at (1)(3). Next, look at (2)(4), where the clone()
method's visibility is java.lang
package and all its subclasses. For the statements "son1.clone();" and "son11.clone();", both clone()
methods are visible in classes Son1
and Son11
, but not in Test1
, so the compilation fails at (2)(4).
Example 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)
}
}
For (1), the clone()
method comes from class MyObject2
itself, so its visibility is package p2
and subclasses of MyObject2
. Although Test2
is a subclass of MyObject2
, it cannot access the protected method clone()
of the base class MyObject2
, so the compilation fails; for (2), since clone()
is accessed on an instance of Test2
which inherits clone()
from MyObject2
, the compilation passes.
Example 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)
}
}
For (1), the clone()
method comes from class Test3
, so its visibility is package p33
and its subclass MyObject3
. Since (1) is called within class Test3
in package p33
, the compilation passes.
Example 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)
}
}
For (1), the clone()
method comes from class MyObject4
, so its visibility is package p4
and its subclass (which does not exist here). Since class Test4
is in package p44
, it does not meet the visibility requirement, so the compilation fails.
Example 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)
}
}
For (1), the clone()
method comes from class MyObject5
, so its visibility is package p5
and its subclass (which does not exist here). Since class Test5
is also in package p5
, it meets the visibility requirement, so the compilation passes.
Example 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)
}
}
For (1), the clone()
method comes from class Test6
, so its visibility is package p6
and its subclass MyObject6
. Since class Test6
is also in package p6
, it meets the visibility requirement, so the compilation passes.
Example 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 {
}
For (1), the clone()
method comes from class Object
, so its visibility is package java.lang
and its subclass Test7
. Since class MyObject7
is not within this scope, it does not meet the visibility requirement, so the compilation fails.
>
Article source: http://blog.csdn.net/justloveyou_/article/details/61672133