Initialization order of constructor
Translation: Cherami
Email: cherami@163.net
Original: http://java.sun.com/jdc/techtips/2000/tt1205.html
Imagine that you are writing programs with Java, and initialize the objects of classes A and B with the following code:
Class a {
INT A = f ();
INT f () {
Return 1;
}
}
Class b extends a {
INT b = a;
INT f () {
Return 2;
}
}
Public class ctordemo1 {
Public static void main (string args []) {
B bobj = new b ();
System.out.println (bobj.b);
}
}
Now, it seems that it is obvious that the value of Bobj.b will be 1 after the initialization is completed. After all, the value of B in class B is initialized by the value of A in class A, and A is initialized by F, and its value is 1, right?
In fact, the value of bobj.b is 2, you have to know why you need to know the initialization of an object.
When an object is created, the initialization is completed in the following order:
1. Set the value of the member for the default initial value (0, false, null)
2. Call the constructor of the object (but there is no construction method body)
3. Call the constructor of the parent class
4. Initialize members using initialization procedures and initial blocks
5. Execute a structural method body
Look at how to do step by step in practice and see the example below:
Class a {
A () {
System.out.println ("a.a caled");
}
}
Class b extends a {
INT i = f ();
Int J;
{
J = 37;
System.out.Println ("Initialization Block Executed");
}
B () {
System.out.println ("B.B Called");
}
INT f () {
System.out.println ("B.f Called");
Return 47;
}
}
Public class ctordemo2 {
Public static void main (string args []) {
B bobj = new b ();
}
}
The output of the program is:
A.a called
B.f Called
Initialization Block Execute
B.B Called
B The construction method is called, but the first thing to do is the constructor of the implicit call parent class. The parent class must be responsible for initializing its own state rather than letting subclasses.
Then the member of the B object is initialized, which contains a call to B.f and initial blocks surrounded in {}. The constructor body of the last B is performed.
You may ask "What is an implicit call for the constructor of the parent class." This means that if the first line of your constructor is not one of the following:
Super ();
Super (args);
THIS ();
THIS (ARGS);
There is a call below:
Super ();
The first row provided to the construction method.
If the class does not construct a configuration? In this case, a default constructor (also called "no parametric configuration method") is automatically generated by the Java compiler. The default constructor only occurs when there is no other construction method without any other construction.
Due to understand this, assume that there is such code in the file a.java: public class a {
Public static void main (string args []) {
A isf = new a ();
}
}
If you want to compile and list the bytecode in A.Class, enter the following:
$ javac a.java
$ javap -c -classpath. a
Output:
Compiled from A.java
Public class a extends java.lang.Object {
Public a ();
Public static void main (java.lang.string []);
}
Method a ()
0 ALOAD_0
1 InvokeSpecial # 1
4 return
Method void main (java.lang.string [])
0 new # 2
3 dup
4 InvokeSpecial # 3
7 ASTORE_1
8 return
In Main, pay attention to the call to the constructor of A (which is the invokespecial line), and a similar to the object constructor generated in the construction method of A.
If the parent class does not have a default constructor, you must explicitly use the "Super (ARGS" call a constructor of the parent class, for example, the following is an error usage:
Class a {
A (INT I) {}
}
Class B Extends a {}
In the above case, a has no default construction method, but the construction method of B must call a constructor of A.
Let's take a look at another example of initialization:
Class a {
A () {
System.out.println ("a.a caled");
}
A (int i) {
THIS ();
System.out.println ("A.A (int) Called");
}
}
Class b extends a {
INT i = f ();
Int J;
{
J = 37;
System.out.Println ("Initialization Block Executed");
}
B () {
THIS (10);
System.out.println ("B.B () Called");
}
B (INT I) {
Super (i);
System.out.Println ("B.B (int) Called");
}
INT f () {
System.out.println ("B.f Called");
Return 47;
}
}
Public class ctordemo3 {
Public static void main (string args []) {
B bobj = new b ();
}
}
The output of the program is:
A.a called
A.a (int) Called
B.f Called
Initialization Block Execute
B.B (int) Called
B.B () Called
This example explicitly uses Super () and this () calls. This () call is another constructor in the same class; this method is called "explicit construct method call". When such a constructor is called, it will perform a usual super () process and subsequent operations. This means that A.a's method is performed before A.A (int), and both are executed before B.B (int) and B.b. If you return the first example, you can answer why printing 2 is 2 instead of 1. B has no construction method, thus generating a default constructor, then it calls Super (), then calls A. The default constructor is generated.
The member in A is then initialized, and the member a is set to the value f () value, but because the B object is being initialized, f () returns a value 2. In other words, the f () method is called in B.
The generation method generated is performed, and then B is initialized, and B is given a value A, that is, 2. Finally, the construction method of B is executed.
The last example illustrates a small variant version of the first example:
Class a {
INT A = f ();
INT f () {
Return 1;
}
}
Class b extends a {
INT b = 37;
INT f () {
Return B;
}
}
Public class ctordemo4 {
Public static void main (string args []) {
B bobj = new b ();
System.out.println (bobj.a);
System.out.println (bobj.f ());
}
}
The output of the program is:
0
37
You may expect the two values of the output Bobj.a and Bobj.f (), but as you can see. This is correct, even in A is initialized from the F method from b, and printed is the value of the F method of A and B.
The problem here is that when A is initialized by the F method call to B, and the method returns the value of member B, and the member has not been initialized. Because this, the value of B is the initial value of 0.
These examples explain the important point in the program - is unwise to call overloaded methods during the construction phase of the object.