关于内存分配,该程序的确切流程如何?

时间:2017-04-22 12:24:41

标签: java

在一次采访中询问了这个问题。 根据我的说法,静态变量首先被初始化。然后执行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();

    }

}

1 个答案:

答案 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