据我所知,当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?
答案 0 :(得分:2)
第二个问题很简单; A
静态初始化的操作顺序为:B.b
被评估,new A(B.b)
被评估(将a
设置为null
),{{1} }被分配a
。如果创建了new A(B.b)
的任何其他实例,则A
将为null。我认为如果没有关于类初始化的详细知识,这应该很容易看到。
第一个问题涉及更多。 JLS的相关章节是chapter 12 on execution。基本思路是:先加载一个类,然后将其链接,然后进行初始化。作为联系的一部分,课程准备;这是在创建静态字段并将其设置为默认值时,对于引用(JLS 12.3.2)a
- 这是在null
初始化之前发生的。
所以事情按此顺序发生:static
已加载并关联,因此A
初始化为a
。然后运行静态初始化程序,因此需要评估null
。现在new A(B.b)
已加载并链接,并且其静态初始化程序已运行,并且B
已经过评估,此时new B(A.a)
为a
并且没有任何特殊情况发生。然后运行null
的构造函数,并将新创建的对象分配给A
。