Many books introducing the Java language (including "Thinking in Java") give a relatively simple introduction to protected, basically just one sentence:Members modified by protected are visible to the current package and its subclasses. This statement is too vague and often causes misunderstandings. In fact, protected visibility lies in two points:

  • Protected members of a base class are visible within the package and to subclasses;
  • If the subclass and the base class are not in the same package, then in the subclass, an instance of the subclass can access the protected methods inherited from the base class, but cannot access the protected methods of an instance of the base class.

We can further master the protected keyword through the following examples about protected method visibility. When encountering a call involving a protected member, first determine where the protected member comes from and what its visibility scope is, then you can judge whether the current usage is feasible. Look at the following seven examples:

Example 1

package p1; public class Father1 { protected void f() {} //The protected method of 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) and (3). The f() method is inherited from class Father1, and its visibility is package p1 and its subclasses Son1 and Son11. Since the package of class Test1 that calls the f() method is also p1, compilation passes at (1) and (3). Next look at (2) and (4). The visibility of the clone() method is the java.lang package and all its subclasses. For the statements "son1.clone();" and "son11.clone();", the clone() methods are visible in classes Son1 and Son11, but not visible to Test1, so compilation fails at (2) and (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, in Test2 you cannot access the protected clone() method of the base class MyObject2, so compilation fails. For (2), since in Test2 what is accessed is the clone() inherited from the base class MyObject2 by its own instance, 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. And (1) is exactly called in class Test3 of package p33, belonging to the same package, so 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 subclasses (there are no subclasses here). But class Test4 is in package p44, so visibility is not satisfied and 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 subclasses (no subclasses here). Class Test5 is also in package p5, so visibility is satisfied and 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. Class Test6 is also in package p6, so visibility is satisfied and 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 the visibility of this clone() method is package java.lang and its subclass Test7. Since class MyObject7 is not in this scope, visibility is not satisfied and compilation fails.

Source: http://blog.csdn.net/justloveyou_/article/details/61672133