1

据我所知,JVM在为A的clinit加载和生成代码时,如果遇到一个未解析的类B,编译器会首先向JVM内部发出一个方法调用来初始化B,然后正常编译B的方法调用/字段使用。所以在运行时,确保 B 在其字段或方法被使用之前被初始化。

如果我在上面犯了任何错误,请纠正我。

然后我不明白JVM如何处理像下面这样的情况。

public class A {
  public static A a = new A(B.b);
  public A(B b) {
    a = null;
  }

  public static void main(String[] args) {
    System.out.println(a == null);
  }
}

public class B {
  public static B b = new B(A.a);
  public B(A a) {}
}

有人可以解释这两个类是如何初始化的,因为它们都需要先初始化另一部分吗?为什么A中的main方法返回false,因为静态字段a应该在A的构造函数中设置为null?

4

1 回答 1

2

第二个问题很简单;静态初始化的操作顺序A是:B.b被评估,new A(B.b)被评估(设置anull),a被分配new A(B.b)A如果创建了任何其他实例,a则为空。我认为如果没有关于类初始化的详细知识,这应该很容易看到。

第一个问题涉及更多一点。JLS 中的相关章节是关于执行的第 12 章。基本思想是这样的:首先加载一个类,然后链接它,然后初始化它。作为链接的一部分,该类已准备好;这是创建其静态字段并将其设置为默认值的时间,即null用于引用(JLS 12.3.2)——这发生在初始化之前static

所以事情按照这个顺序发生:A被加载和链接,所以a被初始化为null. 然后静态初始化程序运行,因此new A(B.b)需要评估。NowB被加载并链接,它的静态初始化程序运行,并被new B(A.a)评估,此时anull并且没有什么特别的事情发生。然后A的构造函数运行并将新创建的对象分配给a.

于 2013-04-04T04:50:33.313 回答