protected
Let’s talk about protected access rights issues. See Example 1 below:
Test.java
class MyObject {} public class Test { public static void main(String[] args) { MyObject obj = new MyObject(); obj.clone(); // Compile error. }} The method clone from the type Object is not visible.
We have already understood that Object.clone() is a protected method. This shows that the method can be accessed by subclasses of the same package (java.lang) and it (java.lang.Object). Here is the MyObject class (the default inheritance of java.lang.Object).
Similarly, Test is also a subclass of java.lang.Object. However, the protected method of another subclass cannot be accessed in one subclass, although the two subclasses inherit from the same parent class.
Let’s look at Example 2 again:
Test2.java
class MyObject2 { protected Object clone() throws CloneNotSupportedException { return super.clone(); }} public class Test2 { public static void main(String[] args) throws CloneNotSupportedException { MyObject2 obj = new MyObject2(); obj.clone(); // Compile OK. }} Here, we override the clone() method of the parent class in the MyObject2 class, call the clone() method in another class Test2, and compile and pass.
The reason for the compilation is obvious. When you override the clone() method in the MyObject2 class, the MyObject2 class and the Test2 class are under the same package, so this protected method is visible to the Test2 class.
At this point, we recall the statements in Chapter 2.2 in the shallow and deep copy articles in Java, ② Overwrite the clone() method of the base class in the derived class and declare it as public. Now I understand the reason for this sentence (in order to enable other classes to call the clone() method of this class, after overloading, the attribute of the clone() method must be set to public).
Let’s take a look at Example 3:
Test3.java
package 1class MyObject3 {protected Object clone() throws CloneNotSupportedException { return super.clone(); }} package 2public class Test3 extends MyObject3 { public static void main(String args[]) { MyObject3 obj = new MyObject3(); obj.clone(); // Compile error. Test3 tobj = new Test3(); tobj.clone();// Complie OK. }} Here I use the Test3 class to inherit MyObject3. Note that these two classes have different packages, otherwise it is the case of Example 2. In the Test3 class, call the clone() method of the instance tobj of Test3 class and compile and pass. And also calling the clone() method of the instance obj of MyObject3 class is called, and the compilation error!
Unexpected results, cann't the protected method be accessed by inherited classes?
It must be clear that class Test3 does inherit class MyObject3 (including its clone method), so you can call your own clone method in class Test3. However, the protected method of the class MyObject3 is invisible to its different bun subclass Test3.
Here is another passage from "java in a nutshell":
protected access requires a little more laboration. Suppose class A declares a protected field x and is extended by a class B, which is defined in a different package (this last point is important). Class B inherits the protected field x, and its code can access that field in the current instance of B or in any other instances of B that the code can refer to. This does not mean, however, that the code of class B can start reading the protected fields of arbitrary instances of A! If an object is an instance of A but is not an instance of B, its fields are obviously not inherited by B, and the code of class B cannot read them.
By the way, many Java books in China are generally described in this way when introducing access permissions (various forms and consistent content):
Access control of the method:
static
1. Keyword static (remember these first, then read it down)
1) Static methods and static variables are objects that belong to a certain class, but not to a class.
2) References to static methods and static variables are directly referenced through class names.
3) Non-static methods and non-static member variables cannot be called in static methods. Otherwise, it is OK.
4) Static variables are similar to global variables in other languages in some program, and can be accessed outside the class if they are not private.
2. When to use static
When we create an instance of a class (object), we usually use the new method so that the data space of this class will be created and its methods can be called.
However, sometimes we hope that although a class can be created with n objects (obviously the data space of these n objects is different), some of the data of these n objects are the same, that is, regardless of how many instances the class has, the data has a memory copy of these instances (see Example 1). This is the case with static variables.
Another scenario is that you want a method not to be associated with any object of the class that contains it. That is to say, this method can be called even if the object is not created. An important usage of the static method is to call it without creating any object (see Example 2). This is the case with a static method.
There is also a special usage in inner classes. Usually, a normal class is not allowed to be declared static, only an inner class can do it. At this time, this inner class declared as static can be used directly as a normal class without the need to instance an outer class (see Example 3). This is the case with static classes.
Example 1
public class TStatic { static int i; public TStatic() { i = 4; } public TStatic(int j) { i = j; } public static void main(String args[]) { System.out.println(TStatic.i); TStatic t = new TStatic(5); // Declare the object reference and instantiate it. At this time i=5 System.out.println(ti); TStatic tt = new TStatic(); // Declare the object reference and instantiate it. At this time i=4 System.out.println(ti); System.out.println(tt.i); System.out.println(ti); }}
result:
05444
The static variable is created when the class is loaded. As long as the class exists, the static variable exists. They must be initialized when defined. In the above example, i is not initialized, so the default initial value 0 will be obtained. The static variable can only be initialized once, and the static variable only accepts the last initialization.
In fact, this is still a problem with multiple instances sharing a static variable.
Example 2
Not declared as static
class ClassA { int b; public void ex1() {} class ClassB { void ex2() { int i; ClassA a = new ClassA(); i = ab; // Here access to the member variable b a.ex1() through object reference; // Here access to the member function ex1 through object reference } }}
Declared as static
class ClassA { static int b; static void ex1() {}} class ClassB { void ex2() { int i; i = ClassA.b; // Here access to the member variable b ClassA.ex1() through the class name; // Here access to the member function ex1 through the class name }} When using static methods, be careful that non-static methods cannot be called in static methods and reference non-static member variables (this or super cannot be referenced in any way in static methods). The reason is very simple. For static things, when the JVM loads the class, it opens up these static spaces in memory (so it can be directly referenced through the class name), and at this time, the class where the non-static methods and member variables are located has not been instantiated.
So if you want to use non-static methods and member variables, you can directly instantiate the class where the method or member variable is located in the static method. That's how public static void main does it.
Example 3
public class StaticCls { public static void main(String[] args) { OuterCls.InnerCls oi = new OuterCls.InnerCls();// There is no need to new OuterCls before this }} class OuterCls { public static class InnerCls { InnerCls() { System.out.println("InnerCls"); } }}
result:
InnerCls
3. Static initialization
The variables defined by static will take precedence over any other non-static variables, regardless of the order in which they appear. A static code block (followed by a piece of code) is used to perform explicit static variable initialization. This code will only be initialized once and when the class is loaded for the first time. See the example below.
class Value { static int c = 0; Value() { c = 15; } Value(int i) { c = i; } static void inc() { c++; }} class Count { public static void prt(String s) { System.out.println(s); } Value v = new Value(10); static Value v1, v2; static { prt("in the static block of cals Count v1.c=" + v1.c + " v2.c=" + v2.c); v1 = new Value(27); prt("in the static block of cals Count v1.c=" + v1.c + " v2.c=" + v2.c); v2 = new Value(); prt("in the static block of cals Count v1.c=" + v1.c + " v2.c=" + v2.c); }} public class TStaticBlock { public static void main(String[] args) { Count ct = new Count(); Count.prt("in the main:"); Count.prt("ct.c=" + ct.vc); Count.prt("v1.c=" + Count.v1.c + " v2.c=" + Count.v2.c); Count.v1.inc(); Count.prt("v1.c=" + Count.v1.c + " v2.c=" + Count.v2.c); Count.prt("ct.c=" + ct.vc); }}
result:
in the static block of calss Count v1.c=0 v2.c=0in the static block of calss Count v1.c=27 v2.c=27 in the static block of calss Count v1.c=15 v2.c=15 in the main:ct.c=10v1.c=10 v2.c=10v1.c=11 v2.c=11ct.c=11
Whether it is v, v1 or v2, the member variables they operate on are the same static variable c.
In the class Count, v1 and v2 (static Value v1, v2;), then initialize the static code block (static{}), and finally initialize v.