Java 为什么我们不能在构造函数中创建非静态自引用对象

Java 为什么我们不能在构造函数中创建非静态自引用对象,java,static,self-reference,Java,Static,Self Reference,当我试图在构造函数中创建具有自引用的对象时,我得到了StackOverflowerError public class Example1 { private int i; private Example1 zero; public Example1(int i) { super(); if (i > 0) { this.i = i; } else { this.i =

当我试图在构造函数中创建具有自引用的对象时,我得到了StackOverflowerError

public class Example1 {
    private int i;
    private Example1 zero;

    public Example1(int i) {
        super();
        if (i > 0) {
            this.i = i;
        } else {
            this.i = this.zero.i;
        }
        this.zero = new Example1(i);
    }

    public int getI() {
        return i;
    }
但当我使用静态引用时,不会发生错误

public class Example2 {
    private int i;
    private static final Example2 ZERO = new Example2(0);

    public Example2() {
        this(ZERO.i);
    }

    public Example2(int i) {
        super();
        this.i = i;
    }

    public int getI() {
        return i;
    }
由于静态对象将在加载类时初始化,因此我能够理解它正在工作


但是在对象创建过程中发生了什么,有人能详细解释一下吗?

examplel1在构造函数中递归创建新实例


静态字段将只创建一次。这就是为什么示例1创建了溢出,而第二个没有。

examplel1在构造函数中递归创建新实例


静态字段将只创建一次。这就是为什么示例1创建了溢出,而第二个没有。

Static修饰符意味着,使其成为静态的内容将在该类的所有对象之间共享。因为我相信您希望在每个Example1对象中创建类似“默认对象”的对象,所以最好的方法是将其设置为静态。这样,您可以创建任意数量的Example1对象(或内存允许),但每个对象都将共享静态Example1 zero对象


这里的非静态对象是不可能的,因为它会尝试在刚才创建的Example1对象中创建另一个Example1对象,当然,在无限循环中会有另一个Example1对象,正如其他人已经说过的。

Static修饰符意味着,您所做的任何静态操作都将在该类的所有对象之间共享。因为我相信您希望在每个Example1对象中创建类似“默认对象”的对象,所以最好的方法是将其设置为静态。这样,您可以创建任意数量的Example1对象(或内存允许),但每个对象都将共享静态Example1 zero对象


这里的非静态对象是不可能的,因为它将尝试在您刚刚创建的Example1对象内创建另一个Example1对象,当然,正如其他人已经说过的那样,在无限循环中会有另一个Example1对象。

这两个代码是相同的吗?我猜不会。
Example2(int)
不会自己调用它,而as
Example1(int)
会不断地调用它自己,endlesslya至少这个错误适合这个站点。但是递归在这里是你的敌人。为什么我能知道原因?这两个代码是一样的吗?我猜不会。
Example2(int)
不会自己调用它,而as
Example1(int)
会不断地调用它自己,endlesslya至少这个错误适合这个站点。但是递归在这里是你的敌人。为什么我能知道原因呢?那么构造函数调用是否只是一个具有特殊语法的方法调用呢?@harinewton你到底想实现什么?你有一个未绑定的递归,不管你把它包装成方法、构造函数还是其他什么东西,它都会崩溃。我真的不明白这个问题。构造函数将创建类的实例。因此,将执行创建实例所需的任何操作。在这一点上,方法没有区别。因此,除了返回值/引用之外,在构造函数中执行的任何操作都可以在方法中完成。当您进行递归调用时,它将是递归的,如果没有条件停止它,则会发生溢出。方法递归调用将仅使用本地状态构建堆栈,但由于它位于构造函数中,因此我在堆栈跟踪中得到Example1.(Example1.java:14)。我想了解在构造函数调用期间会发生什么。构造函数调用不仅仅是另一个方法调用。然而,这是方法调用的一个特例。在对象构造期间,JVM将调用在编译期间合成的方法。在该方法中,将是您添加到构造函数中的代码。这段代码的生命周期对于JVM来说是特殊的,因此它不仅仅是另一个方法调用。但就你所看到的StackOverFlow而言,是的,这就是原因。那么构造函数调用是否只是一个具有特殊语法的方法调用呢?@harinewton你到底想实现什么?你有一个未绑定的递归,不管你把它包装成方法、构造函数还是其他什么东西,它都会崩溃。我真的不明白这个问题。构造函数将创建类的实例。因此,将执行创建实例所需的任何操作。在这一点上,方法没有区别。因此,除了返回值/引用之外,在构造函数中执行的任何操作都可以在方法中完成。当您进行递归调用时,它将是递归的,如果没有条件停止它,则会发生溢出。方法递归调用将仅使用本地状态构建堆栈,但由于它位于构造函数中,因此我在堆栈跟踪中得到Example1.(Example1.java:14)。我想了解在构造函数调用期间会发生什么。构造函数调用不仅仅是另一个方法调用。然而,这是方法调用的一个特例。在对象构造期间,JVM将调用在编译期间合成的方法。在该方法中,将是您添加到构造函数中的代码。这段代码的生命周期对于JVM来说是特殊的,因此它不仅仅是另一个方法调用。但就你所看到的StackOverFlow而言,是的,这就是原因。