在一次采访中询问了这个问题。 根据我的说法,静态变量首先被初始化。然后执行main,它调用类B的构造函数,它在内部调用类A的构造函数(因为超类)。我想知道什么时候分配实例变量的内存到底是什么,程序流总是从超类到子类?
Class A(){
int a = 10;
static int b = 20;
//constructor
A(){}
}
Class B extends A{
int c = 30;
static int d = 40;
B(){}
public static void main(String args[]){
B b = new B();
}
}
答案 0 :(得分:0)
回答第一个问题:如果我们查看解编译的代码,我想知道分配实例变量的内存究竟何时实际上非常简单。假设一个更琐碎的课程:
public class Test {
public Test(){
}
int i = 3;
}
反编译代码(javap -c -p Test.class
)将显示如下内容:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_3
6: putfield #12 // Field i:I
9: return
即使它没有告诉你太多,从这里得到的是,实例字段的初始化被放入构造函数中,所以这就是它发生的时候。
当您拥有静态字段时,情况会有所不同:
public class Test {
static int j = 5;
int i = 3;
}
将生成一个静态代码块,它将在构造函数之前执行:
static {};
Code:
0: iconst_5
1: putstatic #11 // Field j:I
4: return
第二个问题:总是从超类到子类的程序流也很容易,一旦你理解构造函数中的第一个调用是总是在您的示例中调用super
。所以B constructor
实际上是这样的:
B(){
super();
... rest of code
}
在之前初始化B
,您实际上会调用A constructor
,然后调用Object constructor
(因为每个人都继承自Object
)