Java object initialization code
This paper mainly records the initialization process of objects in Java, including the initialization of instance variables and class variables, and the influence of final keyword on initialization. In addition, it also discusses the compile time type and run-time type of reference variables due to inheritance
1、 Initialization of instance variables
Here is the process of creating objects:
When an object of type dog is created for the first time, or when the static field or static method of the dog class is accessed for the first time, the Java interpreter must find dog Class (search in the preset path); when dog.class is found (it will create a class object), all its static initialization modules will run. Therefore, static initialization occurs only once - when the class object is loaded for the first time; when a newdog () is created, The construction process of a dog object will first allocate enough storage space for a dog object in the memory heap; this storage space will be cleared to zero and all primitive types in the dog will be set as their default values (0 is used for numbers and the equivalent settings of Boolean and char); all initializations occurring during member field definition will be executed; the constructor will be executed.
Then, start initializing the instance variable. There are three ways to initialize instance variables:
① Specify initial values when defining instance variables
② Initializing instance variables in a non static initialization block
③ Initializing instance variables in constructor
When the new object is initialized, ① ② should be executed before ③. The order of ① and ② is executed according to the order they are defined in the source code.
When the instance variable is decorated with the final keyword, if the initialization is performed by directly specifying the initial value when defining the final instance variable (mode ①), the initial value of the variable will be determined during compilation, and the final variable is similar to a "macro variable", which is equivalent to a direct constant in Java.
Line 8 outputs false because str3 in line 7 can only be determined after calling the valueof method. Not determined at compile time.
Let's take another example:
If the comment on line 13 is removed, the compilation error "the blank final field str4 may not have been initialized" will be reported
Because the variable str4 is initialized in the constructor. As mentioned earlier: ① when defining an instance variable, directly specify the initial value (initialization of STR1 and STR2), and initialize the instance variable in the non static initialization block (initialization of str3) before initializing the instance variable in the constructor.
In addition, the instance variable decorated with final must be explicitly initialized instead of being initialized by default through the constructor (< clinit >).
STR2 can be initialized to null by default through the constructor. The final modified variable STR1 must be explicitly initialized in the three ways mentioned above. Such as the following test Java (a total of 22 lines of this test class)
Since STR1 is initialized by the ① method, when performing the 15 line: STR1 + STR1 connection operation, STR1 is actually equivalent to a "macro variable"
STR2 and str3 are not "macro variables", so lines 16-17 output false
There is a small difference between initializing variables in the non static initialization code block and initializing variables in the constructor: because the constructor can be rewritten, for example, you initialize an instance variable in a parameterless constructor, but when you call a constructor with parameters in the new object, you must pay attention to whether the instance variable has been initialized correctly.
When a variable is initialized in a non statically initialized code block, the non statically initialized code block will execute whether it calls a constructor with parameters or a constructor without parameters.
2、 Initialization of class variables
Class variables are initialized in two places:
❶ specify initial values when defining class variables
❷ initialization in static initialization code block
No matter how many new objects, the initialization of class variables is performed only once.
3、 Impact of inheritance on initialization
It is mainly to understand the difference between compile time type and run-time type. From this difference, we can see some essential differences between this keyword and super keyword.
The following are noteworthy:
1. The reference variables A and F in line 35 point to the same object in memory. When calling their attributes in lines 36-37, a.color is red and f.color is unknow
Because the declared type (compile time type) of the f variable is fruit, when accessing the attribute, it is determined by the type of the variable declared.
2. In lines 39-40, both a.info() and f.info() output "Apple's method"
Because the runtime type of F variable is apple, info() is a method of the parent class of Apple overload. When a method is called, it is determined by the runtime type of the variable.
3. About this keyword
When a new Apple object is created on line 29 and the getsuper () method is called on line 30, the returnhis on line 4 is finally executed
The explanation of this is to return the object that calls this method. The type it returns is the fruit type (see the return value type of the getthis method), but it is actually the call of the getthis method caused by the apple object. Therefore, the declaration type of this here is fruit, and the runtime type is apple
4. About super keyword
Super is different from this. This can be used to represent the "current object", which can be returned by return. For super, there is no returnsuper; Such a statement.
Super is mainly for the purpose of accessing attributes in the parent class or calling the method in the parent class in the subclass. Like line 24.
5. In the constructor of the parent class, do not call the methods overridden by the child class, or when constructing the parent object, do not rely on those methods overridden by the child class. This is likely to cause initialization failure (the object is not initialized correctly)
Because: as mentioned in points 1 and 2 above, objects (variables) have declaration time types (compile time types) and runtime types. The method invocation depends on the runtime type.
When a new subclass object is, it will first initialize the properties of the parent class. At this time, the runtime type of the object is a subclass. Therefore, if the assignment of the properties of the parent class depends on the overloaded methods in the subclass, the properties of the parent class will not get the correct initialization value. Examples are as follows:
The color attribute of the fruit class is not properly initialized to "unknow", but null
Mainly because line 5 this Getcolor () calls the getcolor method of the apple class. At this time, the color attribute of the apple class inherits directly from the fruit class.
4、 References
Crazy Java breakthrough programmer basic skills Lesson 16 Chapter 2
Effective JAVA Chinese version 2nd Edition Chinese PDF version 2nd Edition Article 17