理解如何加载类和调用静态初始化程序
所以,我只是想确认一下-
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的静态初始化器。
所以它最终应该是循环依赖的?
发布于 2015-05-09 08:56:53
当访问OOMErrorB.c
时,没有加载OOMErrorB
,因为它已经在加载过程中(当JVM最初加载它以调用main
方法时)。一旦在JVM中加载了一个类,它就不会再加载了。因此,不存在循环依赖关系:获取OOMErrorB
的静态成员c
,此时仍未初始化该成员。
您可以检查有关类初始化的本节来自Java语言规范:
因为Java编程语言是多线程的,所以类或接口的初始化需要仔细的同步,因为其他一些线程可能同时尝试初始化同一个类或接口。还有可能递归地请求类或接口的初始化,作为该类或接口初始化的一部分;例如,A类中的变量初始化器可能会调用不相关的B类的方法,而后者又可能调用A类的方法。Java虚拟机的实现负责通过以下过程处理同步和递归初始化。
JVM有其正确的方法锁定类的初始化,以防止递归初始化。
https://stackoverflow.com/questions/30142611
复制相似问题