次のコードがヒープ (OutOfMemoryError など) に相当するスタック オーバーフローを引き起こさない理由がわかりません。静的初期化は、このようなものに対するガードを提供し、代わりに NullPointerException をスローしますか?
編集:私は理解されたとは思わない:
public static void main(String[] args)
から静的メソッドを呼び出しますStaticClass
。このメソッドdoSmth()
を呼び出す前に、StaticClass
最初にロードする必要があります。クラスがロードされると、すべての静的コードが実行されます。StaticClass
クラスでは、は a の値に属性付けされobjClass
た静的フィールドであるため、(をスローする)new ObjClass()
べきではありません。これを行うには をロードする必要があり、これは がロードされているときにすでに発生しているため、明らかにインスタンス化できません(したがって、無限再帰との類推、またはおそらくデッドロックの類推)。問題は、JVM が、ある種の繰り返し呼び出しのために初期化できなかったと言うのではなく、null であると言うことです。null
NullPointerException
new ObjClass()
StaticClass
StaticClass
objClass
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