Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.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_Initialization_Static Initialization_Instance Initializers - Fatal编程技术网

从非静态上下文调用同一类的java构造函数会导致递归,但在静态上下文中可以正常工作吗?

从非静态上下文调用同一类的java构造函数会导致递归,但在静态上下文中可以正常工作吗?,java,initialization,static-initialization,instance-initializers,Java,Initialization,Static Initialization,Instance Initializers,我试图理解Java类的初始化顺序。具体来说,执行静态和实例初始值设定项/字段的时间和顺序。我想出了这样的例子。为什么向自构造函数调用添加static会阻止代码进入递归 public class Test { public static void main(String a[]) { Cons1 c1 = new Cons1(); } } class Cons1 { static Cons1 c = new Cons1(); /* if static is

我试图理解Java类的初始化顺序。具体来说,执行静态和实例初始值设定项/字段的时间和顺序。我想出了这样的例子。为什么向自构造函数调用添加static会阻止代码进入递归

public class Test {
    public static void main(String a[]) {
        Cons1 c1 = new Cons1();
    }
}

class Cons1 {
    static Cons1 c = new Cons1(); /* if static is removed then recursion 
                                    occurs */
    Cons1() {
         //does something
    }
}
静态和实例上下文之间的这种行为差异有什么具体原因吗。我浏览了Java文档,但无法理解这种行为背后的逻辑。对JLS规范的任何解释或参考都会有所帮助

附言:我已经经历了这些,但是我不能从那里得到我的答案

如果一个字段被声明为静态的,那么无论最终创建多少个类实例(可能为零),该字段只存在一个化身。静态字段(有时称为类变量)在初始化类时具体化(§12.4)

另一方面,

如果声明符用于实例变量(即非静态字段),则以下规则适用于其初始值设定项:

  • 在运行时,每次创建类的实例时,都会计算初始值设定项并执行赋值


让我们添加一个
println
语句来了解整个情况:

class Cons1 {
    static Cons1 c = new Cons1();

    Cons1() {
        System.out.println("the constructor was called");
    }

    public static void main(String[] args) {
        Cons1 c1 = new Cons1();
        Cons1 c2 = new Cons1();
    }
}
它三次输出“调用构造函数”:

1-加载类并初始化静态字段
c

2-创建
c1

3-创建
c2

现在,我们将其与带有实例字段的示例进行比较:

class Cons1 {
    Cons1 c = new Cons1();

    Cons1() {
        System.out.println("the constructor was called");
    }

    public static void main(String[] args) {
        Cons1 c1 = new Cons1();
    }
}
很明显,下一个stacktrace没有打印任何内容时失败:

Exception in thread "main" java.lang.StackOverflowError
    at Cons1.<init>(Cons1.java:33)
    ...
    at Cons1.<init>(Cons1.java:33)
线程“main”java.lang.StackOverflower中出现异常 在Cons1.(Cons1.java:33) ... 在Cons1.(Cons1.java:33)
原因是
Cons1
的每个实例都需要另一个
Cons1
对象。因此,我们将调用堆栈中的
Cons1.
方法溢出。因此,当堆栈达到其允许的最大大小时,我们会出现异常。

基本上是相同的原因。您需要理解什么是
static
意味着什么。这是因为a只在类初始化时体现一次。这里的“体现”是否意味着将rhs值分配给参考c?。如果是这样的话,这个变量只有在我们成功创建对象Cons1时才能体现出来。因此,当调用new Cons1()时,full语句尚未完成执行。这不意味着静态变量还没有具体化吗。因此,在创建对象时,此语句将再次执行?它意味着“执行类变量初始值设定项”。jls中是否有“化身”一词的具体解释?谢谢Andrew。你的解释和夹竹桃的评论有助于澄清我的疑问。当然,我需要在jls规格中提供更多内容。