为什么实例变量在构造函数调用之前被初始化? [英] Why instance variables get initialized before constructor called?
问题描述
我有以下代码:
public abstract class UCMService {
private String service;
protected DataMap dataMap = new DataMap();
protected class DataMap extends HashMap< String,String> {
private static final long serialVersionUID = 4014308857539190977L;
public DataMap(){
System.out.println(11111);
put(IdcService,service);
}
}
public UCMService(String service){
System.out.println(2222);
this.service = service;
}
}
在 UCMService
的构造函数之前执行 构造函数.out.println
p>
我想知道为什么会发生。
编译时,编译器将您在声明位置执行的每个初始化移动到类的每个构造函数。因此, UCMService
类的构造函数有效地编译为:
public UCMService (String service){
super(); //首先编译器添加一个super()链接到超类构造函数
dataMap = new DataMap(); //编译器在这里移动初始化(在'super()'之后)
System.out.println(2222);
this.service = service;
}
所以,清楚 DataMap $ c>构造函数在
UCMService
类的打印
语句之前执行。同样,如果你的 UCMService
类中有更多的构造函数,初始化将被移动到所有的。
让我们看一个简单类的字节码:
private String str =rohit;
Demo(){
System.out.println(Hello);
}
}
编译此类,并执行命令 - javap -c Demo
。您将看到以下构造函数的字节代码:
Demo
代码:
0:aload_0
1:invokespecial#1 //方法java / lang / Object。< init>:()V
4:aload_0
5:ldc#2 //字符串rohit
7:putfield#3 //字段str:Ljava / lang / String;
10:getstatic#4 //字段java / lang / System.out:Ljava / io / PrintStream;
13:ldc#5 // String Hello
15:invokevirtual#6 //方法java / io / PrintStream.println:(Ljava / lang / String;)V
18:return
您可以在第7行看到 putfield
,在 print $ c>之前初始化
str
到rohit
$ c>语句( 15
)指令
I have this following piece of code:
public abstract class UCMService{
private String service;
protected DataMap dataMap = new DataMap();
protected class DataMap extends HashMap<String,String> {
private static final long serialVersionUID = 4014308857539190977L;
public DataMap(){
System.out.println("11111");
put("IdcService",service);
}
}
public UCMService(String service){
System.out.println("2222");
this.service = service;
}
}
Now in console the System.out.println
of DataMap
constructor is executing before the constructor of UCMService
.
I was wondering why it is happening.
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
)
这篇关于为什么实例变量在构造函数调用之前被初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!