了解加载类和调用静态初始化程序
In what order do static initializer blocks
所以,我只是想确认一下 -
public class OOMErrorB extends OOMErrorA {
public static int c = 10;
static {
System.out.println("Loading static B " + c);
System.out.println(OOMErrorA.a);
}
public static void main(String[] args) {
new OOMErrorB();
}
}
父类是 -
public class OOMErrorA {
public static int a = 20;
static {
a = a+ OOMErrorB.c;
System.out.println("OOMErrorB.c " + OOMErrorB.c);
System.out.println("loading OOMErrorA.a " + a);
}
}
现在输出B -
的主要方法**
OOMErrorB.c 0
loading OOMErrorA.a 20
Loading static B 10
20
**
我可以理解,首先它是加载A类,因为它是超级类并且称它为静态初始化器,
现在因为我在OOMErrorA的静态块中访问OOMErrorB.c,所以它应该加载并调用OOMErrorB的静态初始化器。 所以,OOMErrorB.c应该是10而不是0。
我对加载和初始化类的了解 -
1) Class and gets loaded and variables are initialized to default values like for int - 0, Object - null.
2) Class field are initialized to specified values.
3) Static block gets called .
在我的程序中,我可以看到类OOMErrorB被加载(步骤1),但步骤2和步骤3没有执行。
然而根据链接上接受的答案,它应该调用OOMErrorB的静态初始化器。
所以它应该以循环依赖结束?
答案 0 :(得分:1)
访问OOMErrorB.c
时,OOMErrorB
未加载,因为它已经处于加载过程中(当JVM最初加载它时,为了调用{{ 1}}方法)。在JVM中加载类后,将不再加载它。因此,不会发生循环依赖:main
的静态成员OOMErrorB
被提取,此时仍未初始化。
您可以查看关于类初始化的this section from the Java language specification:
由于Java编程语言是多线程的,因此初始化类或接口需要仔细同步,因为其他一些线程可能正在尝试同时初始化同一个类或接口。 作为该类或接口的初始化的一部分,还可以递归地请求类或接口的初始化;例如,类A中的变量初始化程序可能会调用不相关的类B的方法,而该方法又可能调用类A的方法。通过使用该方法,Java虚拟机的实现负责处理同步和递归初始化。以下程序。
JVM有正确的方法来锁定类的初始化,以防止递归初始化。