为什么这个Java代码会产生堆栈溢出错误?

ams*_*ams 3 java

执行时,下面的代码会产生堆栈溢出错误.但是,如果删除其中之一

  • static final GenerateStackOverflow E1 = new GenerateStackOverflow("value1");
  • final GenerateStackOverflow E2 = new GenerateStackOverflow("value2");

它在没有堆栈溢出错误的情况下运行.如果我有上面的两行,怎么会出现堆栈溢出错误,但如果只有一行是在类中,则没有错误?

public class GenerateStackOverflow {

    private final String value; 

    static final GenerateStackOverflow E1 = new GenerateStackOverflow("value1");
    final GenerateStackOverflow E2 = new GenerateStackOverflow("value2");


    public GenerateStackOverflow(String value) {
        System.out.println("GenerateStackOverflow.GenerateStackOverflow()");
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public static void main(String[] args) {
        GenerateStackOverflow.class.getName();
    }
}
Run Code Online (Sandbox Code Playgroud)

rge*_*man 5

两者都需要生成一个StackOverflowError.当您包含此行时:

static final GenerateStackOverflow E1 = new GenerateStackOverflow("value1");
Run Code Online (Sandbox Code Playgroud)

GenerateStackOverflow如果首次访问该类,则会创建一个实例.

没有这一行包括:

final GenerateStackOverflow E2 = new GenerateStackOverflow("value2");
Run Code Online (Sandbox Code Playgroud)

事情很好.但这条线很重要.每次GenerateStackOverflow创建实例时,它都会尝试初始化其成员变量E2- 另一个GenerateStackOverflow对象.然后实例将 E2初始化为另一个GenerateStackOverflow对象.这一直持续到StackOverflowError发生.

如果包含第二行但第一行不包含,则不会创建任何实例,并且永远不会输入无限递归.


JB *_*zet 5

构造函数调用自身:

final GenerateStackOverflow E2 = new GenerateStackOverflow("value2");
Run Code Online (Sandbox Code Playgroud)

因此,要构造一个实例,您需要构造一个需要构造实例的实例,等等.

你的程序的main方法加载了这个类.并且有一个静态字段调用类的构造函数,这会创建堆栈溢出.因此,删除静态变量会隐藏问题,因为永远不会调用构造函数.删除非静态变量会完全删除递归调用,从而修复了probem.