根据JLS:
类或接口类型T将在初始化之前立即执行 首次出现以下任何一种情况:
T是一个类,并创建了一个T实例。
它也说,
类的初始化包括执行其静态 初始化器和静态字段的初始化器(类变量) 在课堂上宣布
我从这个推断出两点
现在,
我假设当我在自己的(Test' s)自己的静态初始化程序中创建一个类Test的对象时,它应该给我一个堆栈溢出,因为它应该重复调用自己,因为根据上面两点,实例化类应初始化类,初始化块具有类的实例化。 当我在自己的构造函数或自己的实例初始化程序中实例化类时,会发生堆栈溢出。
例如,
public class Test {
static{
System.out.println("static test");
new Test();
}
{
//new Test(); // This will give a stack overflow
System.out.println("intializer");
}
public Test(){
//new Test(); // This will give a stack overflow
System.out.println("constructor");
}
public static void main(String[] args) {
}
}
但结果却有所不同。
结果:
静态测试 初始化器 构造
要么我太困惑了解班级的初始化,要么我道歉,如果我遗漏了一些非常明显的东西并感谢你的帮助。
答案 0 :(得分:15)
JLS section 12.4.2中指定的类初始化过程的第3步是
如果C的Class对象指示当前线程正在为C进行初始化,那么这必须是初始化的递归请求。释放LC并正常完成。
在其静态初始化程序中创建类的实例不会递归地重新初始化该类;检测到初始化的初始化请求,并且不执行任何操作。
(注意“正常完成”意味着“操作完成”,而不是“按照通常遵循的步骤完成操作”;它与“完全突然完成”相反,这意味着我们得到某种异常或错误。)
答案 1 :(得分:2)
只有在加载类时才会调用静态初始值设定项。在静态初始值设定项中实例化对象不会导致类再次加载,类的类加载只发生一次,类加载器将该类缓存到JVM实例的生命周期。
如果您在实例初始化程序或构造函数中创建了一个新实例,那么您将收到stackoverflow错误。