Today, when writing the constructor method, there is a small problem, caused by this problem a series of thinking, in a Java class in the initialization of variables and classes what is the order of execution?
# # problems found
classstudent{PrivateString name; voidsetName (String name) { This. Name =name; } String GetName () {returnname; } Student () {//This (this.name); This(name); System.out.println ("The topic asks for an argument-free constructor."); } Student (String name) { This. Name =name; } }classteststudent{ Public Static voidMain (string[] args) {Student stu1=NewStudent (); System.out.print (Stu1.getname ()); Student STU2=NewStudent ("Boss"); System.out.println (Stu2.getname ()); }}
Error: cannot reference name before calling the superclass constructor.
When you use the constructor to create an object, the value of the member variable name at this time is initialized, and the error of calling it times in the parameterless construct is what it means. Let's talk about this blog post, what exactly does a class do when it creates objects?
# # Thinking Questions
First, the load is divided into five parts for a class, namely static variables, static blocks, non-static variables, non-static blocks of code, and constructors.
# # # Single class member load order
Test code:
classstudent{//Static Variables StaticString name; //Static code block Static{System.out.println ("Static variable value when you just run to a static code block:" +name); Name= "Static Name value"; System.out.println (Static variable value at end of static code block: "+name); } //define a parameterless constructorStudent () {System.out.println ("Static variable value when you just run to the constructor:" +name); Name= "This is an argument-free constructor"; System.out.println ("Static variable value at the end of the constructor:" +name); } //define a non-static variableString name2; //define a non-static block of code{System.out.println ("Non-static variable value when you just ran to a non-static block of code:" +name2); Name2= "non-static name value"; System.out.println (Non-static variable value at end of non-static code block: "+name2); }}classteststudent{ Public Static voidMain (string[] args) {Student stu=NewStudent (); }}
The result of compiling the code at this point is:
```
Static variable value when just running to a static code block: null
Static variable value at end of static code block: Static Name value
Non-static variable value when just running to a non-static block of code: null
Non-static variable value at end of non-static code block: Non-static name value
Static variable value when you just run to the constructor: static Name Value
Static variable value at the end of the constructor: This is an argument-free constructor
```
It can be seen that when we declare that a class member variable is a static member variable, our static member variable has been generated and initialized to the default value of the corresponding data type (that is, the default value bit of the string object here is null) before the constructor is called.
Then in the static code block, we assign the static variable, and then the program jumps to the non-static variable declaration and assignment. Then execute the non-static code block, and finally go straight to the program's parameterless constructor.
So, with this program code, we conclude that the program loading order for a single class is: Static variable----Static code block---Non-static variable---non-static code block---constructor.
In other words, when the constructor is called, both the static and the non-static properties have finished the initial chemical work, and the This (name) call error does not relate to the Name property itself.
# # # Deep Thinking class loading order
Now that we are in the loading order, we continue to complete the loading order of the class members. About the relationship between a variable and a block of code, or, according to the code above, we have to be open to this preliminary conclusion, because the order in which our programs are loaded is top-down, that is to say, the results we get are probably due to our habitual typesetting, We declare that the order of the parts may affect the conclusions we draw. To determine the rigor of our procedures, we need to further adjust the order of the code to enhance the logic rigor of our code experiments.
Public classStudent2 {//The static code block is put in front, and the name is not declared, so it will error Static{System.out.println ("Static variable value when you just run to a static code block:" +name); Name= "Static Name value"; System.out.println (Static variable value at end of static code block: "+name); } //Static Variables StaticString name; //define a parameterless constructorStudent2 () {System.out.println ("Static variable value when you just run to the constructor:" +name); Name= "This is an argument-free constructor"; System.out.println ("Static variable value at the end of the constructor:" +name); } //define a non-static block of code{System.out.println ("Non-static variable value when you just ran to a non-static block of code:" +name2); Name2= "non-static name value"; System.out.println (Non-static variable value at end of non-static code block: "+name2); } //define a non-static variableString name2;}classteststudent{ Public Static voidMain (string[] args) {Student stu=NewStudent (); Student2 STU2=NewStudent2 (); }}
The result of the above code run:
```
Error: (6, $) Java: illegal forward reference
```
At this point we get the code block in front of the variable declaration and our code has an error, which shows that we are not rigorous in the first place, and we can conclude that the code block is executed before the variable declaration.
So, we can according to common sense Bold conjecture, the order of single class program loading is static-----------------the variable declaration and code block execution order is related to the position before and after the code, and there is no strict before and after, the programmer writes the code in front of the first execution.
# # # Verification conjecture
Public classStudent3 {//define a parameterless constructorStudent3 () {System.out.println ("Static variable value when you just run to the constructor:" +name); Name= "This is an argument-free constructor"; System.out.println ("Static variable value at the end of the constructor:" +name); } //define a non-static block of code{name2= "non-static name value"; System.out.println ("Static variable value at the end of a non-static block of code:" +name); } //define a non-static variableString name2; //Static code block Static{System.out.println ("Run to Static code block");//name = "value assigned in static code block"; } //Static Variables StaticString name;}classteststudent{ Public Static voidMain (string[] args) {Student3 stu3=NewStudent3 (); }}
The result of the above code execution:
```
Run to a static block of code
Static variable value at end of non-static code block: null
Static variable value when just running to the constructor: null
Static variable value at the end of the constructor: This is an argument-free constructor
```
The basic proof of our conjecture is correct, but at the end I did another interesting test.
# # Test
Public classStudent3 {//define a parameterless constructorStudent3 () {System.out.println ("Static variable value when you just run to the constructor:" +name); Name= "This is an argument-free constructor"; System.out.println ("Static variable value at the end of the constructor:" +name); } //define a non-static block of code{name2= "non-static name value"; System.out.println ("Static variable value at the end of a non-static block of code:" +name); } //define a non-static variableString name2; //Static code block Static{System.out.println ("Run to Static code block"); Name= "value assigned in static code block";//According to the truth, we do not have a declaration here to directly assign a value operation } //Static Variables StaticString name;}classteststudent{ Public Static voidMain (string[] args) {Student3 stu3=NewStudent3 (); }}
The result of the above code execution:
```
Run to a static block of code
Static variable value at end of non-static code block: value assigned in static code block
Static variable values when you just run to the constructor: values assigned in static code blocks
Static variable value at the end of the constructor: This is an argument-free constructor
```
That is, in the static code block, we can not refer to the following static variables, but we will be compiled before the assignment, and in the subsequent non-static code block We can also take the value inside, and again make assumptions, this is the Java Virtual machine at compile time to not forward reference, At this point the variable has actually completed a series of operations such as declaring initialization (all exist method areas), but not by compiling.
So I think the first thing we should get is the correct sequence of the entire loading process for the Java program.
This is also possible when the JDK and IDE work together to do something, but in fact it does not affect the existence of our code block is to complete the initialization of the variable, so put the code block before the property declaration is meaningless operation, so here just encountered a test, the actual operation is meaningless.
# # come to the conclusion
Summary: In a class, the order of initialization is:
1. Static variable, static variable initialization;
2. static code block;
3. Initialization of non-static variables;
4. Non-static code block;
5. Constructor.
# #最后
Here, we understand the loading order of each part of a single class, but the problem we mentioned at the beginning of the article is not solved, if the constructor executes after static and non-static properties and blocks of code, then the member variable should already have the initialization value, and then the weak member variable has an initial null value, But it's reported here. Cannot reference name before calling the superclass constructor.
This means that the call to name here is related to the parent class constructor of this class, so we can solve this problem by discussing the loading order of class loading in inheritance later.