所有类的静态初始化程序都已开始执行 - 但为了初始化D,必须初始化C,因此必须初始化B,因此必须初始化A.在A
执行静态初始化器中的代码时,所涉及的所有类都处于"被初始化"状态.
内的静态初始化A
,它构建了一个实例C
-不过C
是已经被初始化,所以初始化不会再次启动......在JVM只是指出,它已经被初始化(在同一个线程内),并继续.
所有这些的细节都在JLS 12.4.2中.子弹特别是:
如果
Class
对象forC
表示当前线程正在为C进行初始化,那么这必须是初始化的递归请求.LC
正常发布并完成.
和
接下来,如果C是一个类而不是一个接口,并且它的超类尚未初始化,那么让SC成为它的超类,让SI1,...,SIn成为C的所有超接口,声明至少一个默认方法.[...]
对于列表中的每个S [SC,SI1,...,SIn],递归地执行S的整个过程.如有必要,首先验证并准备S.
......是相关的.
所有类的静态初始化程序都已开始执行 - 但为了初始化D,必须初始化C,因此必须初始化B,因此必须初始化A.在A
执行静态初始化器中的代码时,所涉及的所有类都处于"被初始化"状态.
内的静态初始化A
,它构建了一个实例C
-不过C
是已经被初始化,所以初始化不会再次启动......在JVM只是指出,它已经被初始化(在同一个线程内),并继续.
所有这些的细节都在JLS 12.4.2中.子弹特别是:
如果
Class
对象forC
表示当前线程正在为C进行初始化,那么这必须是初始化的递归请求.LC
正常发布并完成.
和
接下来,如果C是一个类而不是一个接口,并且它的超类尚未初始化,那么让SC成为它的超类,让SI1,...,SIn成为C的所有超接口,声明至少一个默认方法.[...]
对于列表中的每个S [SC,SI1,...,SIn],递归地执行S的整个过程.如有必要,首先验证并准备S.
......是相关的.
@JonSkeet用技术术语说了一切,我不能说更多.让我试着用类比来解释:
将静态初始化视为打开房间的门,将构造函数执行视为在该房间中执行/完成操作.
现在,打开D房间的门需要打开C门,C需要B,B需要A.现在,你在A房,你在A房完成开门手续.在A房开设手续,你会看到完成C(A c=new C();
)房间工作的笔记.现在,由于C室及其相关房间已经打开,您不需要再打开(意味着没有静态块初始化).但是在你去C房之前,你将完成房间的开业手续,即System.out.println("Static A");
所以,在控制台你有:
静态的A.
现在,你在C室,你必须完成这个房间,但在此之前你因为依赖而完成B和A(C扩展B和B扩展A).所以,在控制台中你有:
Constr A Constr B Constr C.
现在,您将再次回到A室,看到开门手续已经完成.所以,你会来到B室,然后是C,然后是D.所以,在控制台你有:
静态B静态C静态D.
现在,你正在完成房间D(A a=new D();
)的工作,为了做到这一点,你需要完成C,B和C的工作,因为依赖(D扩展C,C扩展B和B扩展A).所以,在控制台中你有:
Constr A Constr B Constr C Constr D.