什么是类的JVM初始化顺序具有另一个类的实例

时间:2016-03-29 14:57:03

标签: java class jvm initialization

假设 JVM 第一次加载了以下Foo类,它刚刚传递给链接步骤(在解析期间)。

public static void main(...) {
     new Foo();
}

public class Foo {

     private static int a = 4;
     private static Hoo hoo = new Hoo();

     Foo (){
         Log.i("Test", ">> Test foo's created!");
     }

}

public class Hoo {

     private static int b = 4;
     private static Soo soo = new Soo();

     Hoo (){
         Log.i("Test", ">> Test hoo's created!");
     }

}

public class Soo {

     private static int b = 4;
     private static Koo soo = new Koo();

     Soo (){
         Log.i("Test", ">> Test soo's created!");
     }

}

...

现在我的问题是这个。我们知道在完成子类构造之前,系统调用递归的基类/超类构造函数。上面的代码中是否存在一些类似的逻辑?我的意思是 JVM 在完成FooHoo()构建后会立即完成Soo()的构建吗?

THX。

1 个答案:

答案 0 :(得分:3)

  

我的意思是JVM在完成Hoo()和Soo()构建后会立即完成Foo的构建吗?

基本上......是的。

根据JLS 12.4.1

  

类或接口类型T将在第一次出现以下任何一个之前立即初始化:

     
      
  • T是一个类,并创建了一个T实例。

  •   
  • 调用T声明的静态方法。

  •   
  • 分配由T声明的静态字段。

  •   
  • 使用T声明的静态字段,该字段不是常量变量(§4.12.4)。

  •   
  • T是顶级类(第7.6节),并且执行在词典内嵌套在T(第8.1.3节)内的断言语句(第14.10节)。

  •   

等等。

在您的示例中,这意味着将按照KooSooHooFoo的顺序初始化类,并执行new Foo() main方法中的表达式将触发此操作。

如果不同类的静态初始化之间存在循环依赖关系,那么事情会变得有点复杂(并且讨厌),但JLS也涵盖了这种边缘情况。