实例初始化程序中的 StackOverflowError

StackOverflowError in Instance Initialiser

这个问题比较理论化。所以我有下面这组代码:

public class Test {

    public static void main(String[] args) {
        Test test = new Test();
    }

    {
        System.out.println("Instance execution");
    }
}

它编译并打印 "Instance Execution"。 但是当我尝试以这种方式执行其他方法时:

public class Test {

    public static void main(String[] args) {
        Test test = new Test();
    }

    {
        System.out.println("Instance execution");
    }

    private void anotherMethod() {
        System.out.println("Method execution");
    }

    {
        Test test = new Test();
        test.anotherMethod();
    }
}

它给我这个错误:

Exception in thread "main" java.lang.WhosebugError
at Test.<init>(Test.java:15)

我完全相信这个错误有最简单的解释,但我的问题是,是构造函数引发了这个错误吗?或者只有系统方法可以这样执行?可执行实例初始化程序的整个方法对我来说是非常新的,所以任何帮助将不胜感激。谢谢

这个:

{
    Test test = new Test();
    test.anotherMethod();
}

是一个实例初始化块。每次创建 Test 实例时都会 运行s。在其中,您正在...创建一个新的 Test 实例,它自然会触发该块,然后创建一个新的 Test 实例,该实例会触发该块...您明白了。

is it the constructor that's throwing this error?

是实例初始化,没错。事实上,在幕后,编译器处理实例初始化块的方式是将该代码逐字复制到 class 中每个构造函数的开头(包括默认构造函数,如果您不提供默认值),就在对 super 的任何调用之后(如果没有明确的调用,则为默认值)。所以你可以说这是构造函数抛出错误,即使概念上,它是实例初始化,与构造函数本身不同。

Or only System methods can be executed this way?

不确定 "System methods," 是什么意思,但问题是每个实例的初始化块是 运行。如果你只想要 运行 一次,在 class 初始化时,你可以使用 static 初始化块:

public class Test {

    public static void main(String[] args) {
        Test test = new Test();
    }

    {
        System.out.println("Instance execution");
    }

    private void anotherMethod() {
        System.out.println("Method execution");
    }

    static // <==================
    {
        System.out.println("Class initialization"); // ***
        Test test = new Test();
        test.anotherMethod();
    }
}

输出:

Class initialization
Instance execution
Method execution
Instance execution

(我们看到 "Instance execution" 两次,因为 main 中有一个 new Teststatic 初始化块中有另一个。)

但实际上,最简单的事情是将对 anotherMethod 的调用放在 main 中:

public class Test {

    public static void main(String[] args) {
        Test test = new Test();
        test.anotherMethod();
    }

    {
        System.out.println("Instance execution");
    }

    private void anotherMethod() {
        System.out.println("Method execution");
    }
}

输出

Instance execution
Method execution

问题是,您在构造函数中创建了一个 Test 对象,这将创建另一个 Test 对象,依此类推。而是使用

this.anotherMethod();