在自己的静态初始化程序中创建类的对象

时间:2015-07-20 02:16:40

标签: java static language-lawyer

根据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) {
    }

}

但结果却有所不同。

结果:

  

静态测试   初始化器   构造

要么我太困惑了解班级的初始化,要么我道歉,如果我遗漏了一些非常明显的东西并感谢你的帮助。

2 个答案:

答案 0 :(得分:15)

JLS section 12.4.2中指定的类初始化过程的第3步是

  

如果C的Class对象指示当前线程正在为C进行初始化,那么这必须是初始化的递归请求。释放LC并正常完成。

在其静态初始化程序中创建类的实例不会递归地重新初始化该类;检测到初始化的初始化请求,并且不执行任何操作。

(注意“正常完成”意味着“操作完成”,而不是“按照通常遵循的步骤完成操作”;它与“完全突然完成”相反,这意味着我们得到某种异常或错误。)

答案 1 :(得分:2)

只有在加载类时才会调用静态初始值设定项。在静态初始值设定项中实例化对象不会导致类再次加载,类的类加载只发生一次,类加载器将该类缓存到JVM实例的生命周期。

如果您在实例初始化程序或构造函数中创建了一个新实例,那么您将收到stackoverflow错误。