This is because at compile time, the compiler moves every initialization you have done at the place of declaration to every constructor of your class. So the constructor of UCMService class is effectively compiled to:
public UCMService(String service){
super(); // First compiler adds a super() to chain to super class constructor
dataMap = new DataMap(); // Compiler moves the initialization here (right after `super()`)
System.out.println("2222");
this.service = service;
}
So, clearly DataMap() constructor is executed before the print statement of UCMService class. Similarly, if you have any more constructor in your UCMService class, the initialization will be moved to all of them.
Let's see the byte code of a simple class:
class Demo {
private String str = "rohit";
Demo() {
System.out.println("Hello");
}
}
compile this class, and execute the command - javap -c Demo. You will see the following byte code of constructor:
Demo();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: ldc #2 // String rohit
7: putfield #3 // Field str:Ljava/lang/String;
10: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
13: ldc #5 // String Hello
15: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
18: return
You can see the putfield instruction at line 7, initializes field str to "rohit", which is before the print statement (instruction at line 15)