初期化の問題
2506 ワード
「.class」を使用してClassオブジェクトへの参照を作成する場合、そのClassオブジェクトは自動的に初期化されません.
クラスを使用するための準備作業には、実際には3つのステップがあります.
1.ロードします.これはクラスローダによって実行されます.このステップでは、バイトコードを検索し、これらのバイトコードからClassオブジェクトを作成します.
2.リンク.このフェーズでは、クラス内のバイトコードを検証し、静的ドメインにストレージスペースを割り当て、必要に応じて、このクラスが作成した他のクラスへのすべての参照を解析します.
3.初期化.クラスにスーパークラスがある場合は、クラスを初期化し、静的初期化器と静的初期化ブロックを実行します.
初期化は、静的メソッド(コンストラクタが暗黙的に静的である)または非常数の静的ドメインを最初に参照するときに遅延されます.
1.initableリファレンスの作成から、.class構文のみを使用してクラスへのリファレンスを取得しても初期化は開始されません.
2.Class.forName()のメソッドは、initable 3の参照の作成など、すぐに初期化されます.
3.Initable.staticFinalの値が「コンパイル期間定数」である場合、この値はInitableクラスを初期化する必要がなく読み込むことができます.
4.ドメインをstatic finalに設定するだけでは、コンパイル期間定数ではないため、Initable.staticFinal 2へのアクセスなど、この動作を確保するには十分ではありません.
5.staticドメインがfinalでない場合、アクセスするときは、常に読み取り前にリンク(このドメインにストレージスペースを割り当てる)と初期化(ストレージスペースを初期化)を行う必要があります. ),Initable 2.staticNonFinalへのアクセスで見たように.
クラスを使用するための準備作業には、実際には3つのステップがあります.
1.ロードします.これはクラスローダによって実行されます.このステップでは、バイトコードを検索し、これらのバイトコードからClassオブジェクトを作成します.
2.リンク.このフェーズでは、クラス内のバイトコードを検証し、静的ドメインにストレージスペースを割り当て、必要に応じて、このクラスが作成した他のクラスへのすべての参照を解析します.
3.初期化.クラスにスーパークラスがある場合は、クラスを初期化し、静的初期化器と静的初期化ブロックを実行します.
初期化は、静的メソッド(コンストラクタが暗黙的に静的である)または非常数の静的ドメインを最初に参照するときに遅延されます.
import java.util.*;
class Initable {
static final int staticFinal = 47;
static final int staticFinal2 =
ClassInitialization.rand.nextInt(1000);
static {
System.out.println("Initializing Initable");
}
}
class Initable2 {
static int staticNonFinal = 147;
static {
System.out.println("Initializing Initable2");
}
}
class Initable3 {
static int staticNonFinal = 74;
static {
System.out.println("Initializing Initable3");
}
}
public class ClassInitialization {
public static Random rand = new Random(47);
public static void main(String[] args) throws Exception {
Class initable = Initable.class;
System.out.println("After creating Initable ref");
// Does not trigger initialization:
System.out.println(Initable.staticFinal);
// Does trigger initialization:
System.out.println(Initable.staticFinal2);
// Does trigger initialization:
System.out.println(Initable2.staticNonFinal);
Class initable3 = Class.forName("Initable3");
System.out.println("After creating Initable3 ref");
System.out.println(Initable3.staticNonFinal);
}
}
/* Output:
After creating Initable ref
47
Initializing Initable
258
Initializing Initable2
147
Initializing Initable3
After creating Initable3 ref
74
*///:~
1.initableリファレンスの作成から、.class構文のみを使用してクラスへのリファレンスを取得しても初期化は開始されません.
2.Class.forName()のメソッドは、initable 3の参照の作成など、すぐに初期化されます.
3.Initable.staticFinalの値が「コンパイル期間定数」である場合、この値はInitableクラスを初期化する必要がなく読み込むことができます.
4.ドメインをstatic finalに設定するだけでは、コンパイル期間定数ではないため、Initable.staticFinal 2へのアクセスなど、この動作を確保するには十分ではありません.
5.staticドメインがfinalでない場合、アクセスするときは、常に読み取り前にリンク(このドメインにストレージスペースを割り当てる)と初期化(ストレージスペースを初期化)を行う必要があります. ),Initable 2.staticNonFinalへのアクセスで見たように.