我不明白为什么下面的代码不是这个原因,导致堆栈溢出等同于堆(OutOfMemoryError之类的东西),因为它是某种无限递归(不是吗?)。静态初始化是否可以防止此类情况发生,而是抛出NullPointerException?

编辑:我不相信我被理解:
public static void main(String[] args)StaticClass调用静态方法。需要先加载名为doSmth()StaticClass方法。当一个类被加载时,所有的静态代码都被运行。在StaticClass类中,objClass是具有new ObjClass()值的静态字段,因此不应为null(抛出NullPointerException)。显然,无法实例化new ObjClass(),因为要执行此操作,您需要加载StaticClass,并且在加载StaticClass时已经发生(因此具有无限递归的类比,或者可能是死锁类比)。问题是JVM表示objClass为null,而不是说由于某种重复调用而无法初始化new ObjClass()

在正常情况下,由于调用方而引发NullPointerException。但是在这种情况下,您只能更改被呼叫者(在ObjClass构造函数中删除带有注释的行),然后您将不会收到NullPointerException

package pack;

public class ObjClass
{
    public ObjClass() {
        StaticClass.doSmth();//if removed, no NullPointerException
    }

    public String getSomething() {
        return "get";
    }

    public static void main(String[] args) {
        StaticClass.loadStaticClass();
    }
}

class StaticClass {
    private static ObjClass objClass = new ObjClass();

    static void loadStaticClass() {
    }

    static void doSmth()             {
        System.out.println(objClass.getSomething());
    }
}


这使:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at pack.ObjClass.main(ObjClass.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.NullPointerException
    at pack.ObjClass$StaticClass.doSmth(ObjClass.java:39)
    at pack.ObjClass.<init>(ObjClass.java:20)
    at pack.ObjClass$StaticClass.<clinit>(ObjClass.java:34)
    ... 6 more

最佳答案

引用StaticClass实例化objClass,该实例调用ObjClass构造函数,该构造函数调用doSmth()。它使用引用objClass,但尚未分配,因为它需要完全构造的objClass进行引用。

简而言之,

this.x = doMethod();


在将引用doMethod()分配给结果之前,需要完成x

你想做什么 ?还是这是一种锻炼?

08-24 23:13