I have this following piece of code:
public abstract class UCMService{
private String service;
protected DataMap dataMap = new DataMap();
Short answer:
Because the spec says so.
Long answer:
It would be very strange for the constructor to be unable to use inline-initialized fields.
You want to be able to write
SomeService myService = new SomeService();
public MyConstructor() {
someService.doSomething();
}
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
)