Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在类自身的静态初始值设定项中创建类的对象_Java_Static_Language Lawyer - Fatal编程技术网

Java 在类自身的静态初始值设定项中创建类的对象

Java 在类自身的静态初始值设定项中创建类的对象,java,static,language-lawyer,Java,Static,Language Lawyer,根据: 类或接口类型T将在 首次出现以下任何一种情况: T是一个类,并创建了T的一个实例。 还说, 类的初始化包括执行其静态 初始值设定项和静态字段的初始值设定项(类变量) 在课堂上宣布 我由此推断出两点 类初始化包括执行其静态初始值设定项 如果类被实例化,则会发生类初始化 现在, 我假设当我在自己的(测试自己的)静态初始值设定项中创建类测试的对象时,它应该抛出堆栈溢出,因为它应该重复调用自己,因为根据上述两点,类的实例化应该初始化类,初始化块具有类的实例化。当我在类自己的构造函数或实例初始

根据:

类或接口类型T将在 首次出现以下任何一种情况:

T是一个类,并创建了T的一个实例。

还说,

类的初始化包括执行其静态 初始值设定项和静态字段的初始值设定项(类变量) 在课堂上宣布

我由此推断出两点

  • 类初始化包括执行其静态初始值设定项
  • 如果类被实例化,则会发生类初始化
现在,

我假设当我在自己的(测试自己的)静态初始值设定项中创建类测试的对象时,它应该抛出堆栈溢出,因为它应该重复调用自己,因为根据上述两点,类的实例化应该初始化类,初始化块具有类的实例化。当我在类自己的构造函数或实例初始值设定项中实例化该类时,会发生堆栈溢出

比如说,

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

}
然而,结果却有所不同

结果:

静态试验 初始化器 建造师


要么我对类的初始化理解太混乱,要么如果我在这里遗漏了一些非常明显的东西,我向您道歉,并感谢您的帮助。

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


如果在实例初始值设定项或构造函数中创建了新实例,则会出现stackoverflow错误。

中指定的类初始化过程的步骤3是

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

在静态初始值设定项中创建类的实例不会递归地重新初始化该类;递归初始化请求被检测到,不做任何事情


(请注意,“正常完成”表示“操作已完成”,而不是“按照正常步骤完成操作”;它与“突然完成”相反,这意味着我们遇到了某种异常或错误。)

静态块只调用一次。。“为什么你认为它会被多次调用?”康斯坦丁说,因为JLS是这么说的。(或者更准确地说,这意味着在这种情况下,静态初始值设定项必须在静态初始值设定项运行之前运行)Constantin,感谢您的响应,我认为静态块正在创建类本身的对象,该对象将再次初始化类(如果是blooper,则对我进行duh,但我在这里感到困惑),不管怎样,我相信静态块只被调用一次,并且该块正在实例化类本身,它只是一个单例对象?还有:这是一个“为什么在实践中会发生这种情况?”类型的问题还是一个语言律师类型的问题?(“这应该发生吗?”)在类加载器中,实例的初始化和类的初始化之间存在差异。。你怎么知道我是律师?谢谢你的回复,主执行线程只通过类加载器加载了一次测试类,静态初始化器中的对象是singletonRelease LC,并且正常完成。。怎样?我的意思是,由于它是递归调用,当前线程正在尝试初始化类静态代码请求初始化的类,它将如何顺利结束?你能再解释一下吗possible@Babel:“正常完成”是在别处定义的技术术语。这基本上意味着我们完成了;这并不意味着我们必须做其他事情来完成。不做任何事情是很容易理解的,在这个时候,类还没有完全初始化,但它允许访问它的静态字段和方法,对吗?但为什么需要释放信用证?当前线程正在初始化类并接收递归初始化请求,它知道没有其他线程在请求,释放LC毫无意义。@Richard:我们为什么要一直保留LC?我们不需要在初始化的整个过程中保持它;在初始化的开始和结束时,只需要很短的时间。特别是,我看不到任何要求初始化锁是可重入的,因此释放锁可以防止递归初始化请求出现死锁。@user2357112如果LC在初始化期间未保持,锁到底保护什么?初始化的状态?