在它自己的静态初始化器中创建一个 class 的对象

Creating an object of a class in its own static initializer

根据JLS

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

T is a class and an instance of T is created.

还说,

Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class

由此推断出两点

现在,

我假设当我在它自己的(测试自己的)静态初始化程序中创建一个 class 测试的对象时,它应该抛出一个堆栈溢出,因为它应该重复调用自己,因为根据以上两点, class 的实例化应该初始化 class 并且初始化块具有 class 的实例化。 当我在它自己的构造函数或它自己的实例初始化器中实例化 class 时发生堆栈溢出。

例如,

public class Test {

    static{
        System.out.println("static test");
        new Test();
    }
    {
       //new Test(); // This will give a stack overflow
        System.out.println("intializer");
    }

    public Test(){
        //new Test(); // This will give a stack overflow
        System.out.println("constructor");
    }
    public static void main(String[] args) {
    }

}

然而结果却有所不同。

结果:

static test intializer constructor

要么我对 class 的初始化理解太混乱,要么如果我在这里遗漏了一些非常明显的东西,我深表歉意,感谢您的帮助。

静态初始化程序仅在加载 class 时调用。在静态初始化器中实例化对象不会导致 class 再次加载,class 加载 class 只发生一次,classloader 缓存class JVM 实例的生命周期。

如果您在实例初始值设定项或构造函数中创建了一个新实例,则会出现 Whosebug 错误。

JLS section 12.4.2 中指定的 class 初始化过程的第 3 步是

If the Class object for C indicates that initialization is in progress for C by the current thread, then this must be a recursive request for initialization. Release LC and complete normally.

在其静态初始化程序中创建 class 的实例不会递归地重新初始化 class;检测到初始化的递归请求并且不执行任何操作。

(请注意,"complete normally" 表示 "the operation is done",而不是 "follow the steps that would normally be followed to complete the operation";它与 "complete abruptly" 相反,这意味着我们遇到了某种异常或错误。)