Ответ 1
Это связано с тем, что во время компиляции компилятор перемещает каждую инициализацию, выполненную вами в месте объявления, каждому конструктору вашего класса. Таким образом, конструктор класса UCMService
эффективно скомпилирован для:
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;
}
Итак, ясно, что конструктор DataMap()
выполняется перед оператором print
класса UCMService
. Аналогично, если у вас есть еще один конструктор в вашем классе UCMService
, инициализация будет перенесена на все из них.
Посмотрим на байтовый код простого класса:
class Demo {
private String str = "rohit";
Demo() {
System.out.println("Hello");
}
}
скомпилируйте этот класс и выполните команду - javap -c Demo
. Вы увидите следующий байтовый код конструктора:
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
Вы можете увидеть инструкцию putfield
в строке 7, инициализировать поле str
до "rohit"
, которое находится перед оператором print
(команда в строке 15
)