【问题标题】:Why we are not able to create non-static self-referential object in constructor为什么我们不能在构造函数中创建非静态自引用对象
【发布时间】:2014-07-01 17:16:03
【问题描述】:

当我尝试在构造函数中创建具有自引用的对象时,我收到了 StackOverflowError。

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;
    }

由于静态对象将在加载类时被初始化,所以我能够理解它正在工作。

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

【问题讨论】:

  • 两个代码一样吗?我猜没有。
  • Example2(int) 不会自称自己,而Example1(int) 会不断自称
  • 至少该错误适用于该站点。但是递归是你的敌人。
  • 为什么投反对票我能知道原因吗?

标签: java static self-reference


【解决方案1】:

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

静态字段只会被创建一次。这就是示例 1 创建溢出而第二个没有的原因。

【讨论】:

  • 那么构造函数调用是否只是特殊语法的方法调用?
  • @harinewton 你到底想达到什么目的?你有无限递归,不管你把它包装成方法、构造函数还是其他任何东西,它都会崩溃。
  • 我其实不明白这个问题。构造函数将创建一个类的实例。因此,将执行创建实例所需的任何内容。在这一点上,方法没有区别。因此,您在构造函数中所做的任何事情都可以在方法中完成,除了返回值/引用。当你进行递归调用时,它会递归,如果没有条件停止它,就会发生溢出。
  • 一个方法递归调用将只是建立具有本地状态的堆栈,但由于它在构造函数中,所以我在堆栈跟踪中得到 Example1.(Example1.java:14)。我想了解在构造函数调用期间会发生什么。
  • 构造函数调用不仅仅是另一个方法调用。然而,它是方法调用的一种特殊情况。在对象构造期间,JVM 将调用它在编译期间合成的称为 的方法。在该方法中将是您添加到构造函数的代码。这段代码的生命周期对于 JVM 来说是特殊的,因此它不仅仅是另一个方法调用。但就您看到的 StackOverFlow 而言,是的,这就是原因。
【解决方案2】:

Static 修饰符意味着您设置为静态的任何内容都将在该类的所有对象之间共享。由于我相信您想在每个 Example1 对象中创建类似“默认对象”的东西,因此最好的方法是将其设为静态。这样,您可以根据需要(或您的内存允许)创建任意数量的 Example1 对象,但每个对象都将共享静态 Example1 零对象。

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

【讨论】:

    猜你喜欢
    • 2020-11-01
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多