静态修饰符会产生如此巨大的差异,发生了什么?

时间:2015-01-15 13:16:28

标签: java

我创建一个类如下:

public class NodeOne {

    NodeOne nodeone = new NodeOne();

    public NodeOne() {
        System.out.println("1");
    }

    public static void main(String[] args) {
        NodeOne nodeone = new NodeOne();
    }
}

一旦我运行它,我得到异常“线程中的异常”主“java.lang.StackOverflowError “,我知道确定的原因。但是当我在场节点之前添加修饰符”static“时,结果就好了。那么深层原因是什么?

public class NodeOne {

    static NodeOne nodeone = new NodeOne();

    public NodeOne() {
        System.out.println("1");
    }

    public static void main(String[] args) {
        NodeOne nodeone = new NodeOne();
    }
}

输出:
     1

1

3 个答案:

答案 0 :(得分:2)

在第一种情况下,每次创建新对象NodeOne时,其默认构造函数都会为其字段nodeone调用另一个构造函数。它再次发生,又一次又一次......直到堆栈已满。

当它是静态的时,它只被调用一次,第一次使用这个类。

答案 1 :(得分:1)

第一个例子的问题是NodeOne类包含同一个类的实例。

当初始化类时,成员字段被初始化,这反过来导致它自己的字段被初始化,依此类推,在一个永无止境的循环中(实际上它在jvm达到最大堆栈大小时结束,因为每个构造函数都被调用使用了一点)。

一般认为在课堂上设置这样的字段是不好的做法,因为它可能导致这种类型或错误。请注意,可以在main中实例化该类。

答案 2 :(得分:0)

这里的问题是您正在进行递归通话。当您调用构造函数NodeOne()时,它会尝试转到类NodeOne并检查其属性。它在那里找到属性nodeone,它需要使用构造函数进行实例化,该构造函数将为新实例分配新的内存地址。此实例还包含属性nodeone,该属性也需要实例化。在这里它循环并循环,直到它消耗所有JVM内存。但是如果你使用static,它将只分配一个内存地址,其内容java将为每个实例化进行修改。