Java initialization block, static initialization block, execution sequence and usage of constructor, java Constructor

Source: Internet
Author: User

Java initialization block, static initialization block, execution sequence and usage of constructor, java Constructor

 

Java differs from C ++ in that Java not only has constructor, but also has the Initialization Block concept. The following describes the execution sequence and possible uses.

Execution sequence

First, define three classes A, B, and C for testing. B inherits A, C inherits B, the static initialization blocks, non-static initialization blocks, and constructors are added to them respectively, which are a simple output.

The Main class is also like this.

1 class A {2 static {3 System. out. println ("Static init. "); 4} 5 6 {7 System. out. println ("Instance init. "); 8} 9 10 A () {11 System. out. println ("Constructor. "); 12} 13} 14 15 class B extends A {16 static {17 System. out. println ("Static init B. "); 18} 19 20 {21 System. out. println ("Instance init B. "); 22} 23 24 B () {25 System. out. println ("Constructor B. "); 26} 27} 28 29 class C extends B {30 31 static {32 System. out. println ("Static init C. "); 33} 34 35 {36 System. out. println ("Instance init C. "); 37} 38 39 C () {40 System. out. println ("Constructor C. "); 41} 42} 43 44 public class Main {45 46 static {47 System. out. println ("Static init Main. "); 48} 49 50 {51 System. out. println ("Instance init Main. "); 52} 53 54 public Main () {55 System. out. println ("Constructor Main. "); 56} 57 58 public static void main (String [] args) {59 C c = new C (); 60 // B B B = new B (); 61} 62}Test code

 

Of course, internal classes are not used here, because internal classes cannot use static definitions, while static internal classes lose their universality.

As you can see, when the program enters the main function and creates an object of class C, the output is like this:

Static init Main.Static init A.Static init B.Static init C.Instance init A.Constructor A.Instance init B.Constructor B.Instance init C.Constructor C.

 

Observe the above output and observe two interesting phenomena:

If there are multiple instantiated objects, will they change? So after the First Class C object, instantiate a Class B object and observe the output:

Static init Main.Static init A.Static init B.Static init C.Instance init A.Constructor A.Instance init B.Constructor B.Instance init C.Constructor C.Instance init A.Constructor A.Instance init B.Constructor B.

 

We can see that this output is basically the same as above, right? There are only four more lines in the end, which is the information generated when the new class B object is instantiated. It is also the initialization block and constructor of the parent class A to be executed first, the next step is to initialize the block and constructor of subclass B. At the same time, it is found that the output of the static initialization block only appears once, that is to say, the static initialization block of each class is executed only once when the class object is instantiated for the first time.

In any case, the initialization block and constructor are always executed together. Let's decompile it!

View the generated directory and find that four directories have been generated. class file, which is. class, B. class, C. class, Main. class, first look at Main. class Structure (new B is re-Annotated here ):

1 javap -c Main
1 Compiled from "Main. java "2 public class Main {3 public Main (); 4 Code: 5 0: aload_0 6 1: invokespecial #1 // Method java/lang/Object. "<init>" :() V 7 4: getstatic #2 // Field java/lang/System. out: Ljava/io/PrintStream; 8 7: ldc #3 // String Instance init Main. 9 9: invokevirtual #4 // Method java/io/PrintStream. println :( Ljava/lang/String;) V10 12: getstatic #2 // Field java/lang/System. out: Ljava/io/PrintStream; 11 15: ldc #5 // String Constructor Main.12 17: invokevirtual #4 // Method java/io/PrintStream. println :( Ljava/lang/String;) V13 20: return14 15 public static void main (java. lang. string []); 16 Code: 17 0: new #6 // class C18 3: dup19 4: invokespecial #7 // Method C. "<init>" :() V20 7: astore_121 8: return22 23 static {}; 24 Code: 25 0: getstatic #2 // Field java/lang/System. out: Ljava/io/PrintStream; 26 3: ldc #8 // String Static init Main.27 5: invokevirtual #4 // Method java/io/PrintStream. println :( Ljava/lang/String;) V28 8: return29}Decompilation result of Main. class

 

We can see that the entire Main class is divided into three parts. The static {} part is obviously our static initialization block, which calls println and outputs the String "Static init Main. "; the main entry function is also very clear. First, a new class C object is instantiated, then the constructor of class C is called, and finally the result is returned; and the above public Main (); this is the Main constructor, but we can see that the println is called twice, and the String "Instance init Main. "And String" Constructor Main. ". Is the initialization block and constructor merged?

Let's look at the decompilation results of class C:

1 javap -c C
Compiled from "Main. java "class C extends B {C (); Code: 0: aload_0 1: invokespecial #1 // Method B. "<init>" :() V 4: getstatic #2 // Field java/lang/System. out: Ljava/io/PrintStream; 7: ldc #3 // String Instance init C. 9: invokevirtual #4 // Method java/io/PrintStream. println :( Ljava/lang/String;) V 12: getstatic #2 // Field java/lang/System. out: Ljava/io/PrintStream; 15: ldc #5 // String Constructor C. 17: invokevirtual #4 // Method java/io/PrintStream. println :( Ljava/lang/String;) V 20: return static {}; Code: 0: getstatic #2 // Field java/lang/System. out: Ljava/io/PrintStream; 3: ldc #6 // String Static init C. 5: invokevirtual #4 // Method java/io/PrintStream. println :( Ljava/lang/String;) V 8: return}C. decompilation result of class

 

The static initialization block is still separated by a part, and our debugging statement is output. The other part is still the constructor C () of Class C. It can be seen that it calls the constructor of Class B first, and then outputs the statements in the initialization block, then output the statements we wrote in the constructor and finally returned. This is also true for multiple tests. So we can infer that the code of the initialization block is added to the front of the subclass constructor, and the back of the parent class initialization.

 

Possible Uses:

Since the execution sequence and general principles have been clarified, we need to explore the possible use of the initialization block.

Static initialization Block

1. used to initialize static member variables

For example, to add a static member variable sub to Class C, we assign it 5 in the static block:

 1 class C extends B { 2  3     static public int a; 4  5     static { 6         a = 5; 7         System.out.println("Static init C."); 8     } 9 10 ......11 12 }

The main function outputs the static variable C. sub:

1 public static void main(String[] args) {2     System.out.println("Value of C.sub: " + C.sub);3 }

The output result is as follows:

Static init Main.Static init A.Static init B.Static init C.Value of C.sub: 5

The class conforms to the conclusion that the static initialization block is executed when it is loaded for the first time, and C. sub is correctly assigned to 5 and output.

But at first glance it seems useless, because static member variables can be assigned values by the way during definition. Therefore, it is a bit difficult to assign values.

 

2. Execute the initialization code

For example, you can record the logs of the first sort class or facilitate the initialization of the singleton mode. In Singleton mode, you can first initialize some basic parameters that may be accessed by other classes with the static block, and then construct the monomer when a large amount of resources need to be loaded (getInstance, load Resources in the constructor.

 

Non-static initialization Block

This is nothing to say. It is basically a function of constructor, but it is executed before constructor. The most common usage should beCode reuseThat is, if multiple overloaded constructors have several same code segments, you can pull the repeated code out and put it in the initialization block. However, pay attention to the execution sequence, initialization code with strict requirements on the sequence is not suitable for use.

 

Summary:

 

This article is based on the knowledge sharing signature-non-commercial use-share the 4.0 International License Agreement for publishing in the same way. You are welcome to reference, repost, or deduct this article, but you must keep this article's signature BlackStorm and link http://www.cnblogs.com/blackstorm/p. If you have any questions or authorization negotiation, please contact me.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.