Java初期化の順序
まずJavaの初期化についてお話しします. オブジェクトの初期化作業は、オブジェクトが呼び出される前に完了する必要があります.では、オブジェクトを作成するときにクラスの初期化メソッドを呼び出す必要があります.このメソッドが構築メソッドです.コンストラクションメソッド名が一意であること,すなわちJavaコンパイラに識別できることを確保するために,ここではクラス名が全く同じ方法をコンストラクションメソッドとして用いる.コンストラクションメソッドでは、リロードは許可されますが、値は返されません.Javaオブジェクトの初期化の手順を見てみましょう. クラス内部では,変数定義の前後順序が初期化の順序を決定する.変数定義がメソッド定義間に分散しても、構築メソッドを含む任意のメソッド呼び出しの前に初期化されます.しかし、静的変数という特殊な状況があります.静的変数は非静的変数の初期化前に初期化され、静的変数の初期化は必要な時点でのみ行われ、一度のみ初期化されます.最後にJavaクリーンアップを見てみましょう. Javaでは、不要なオブジェクトが占有するメモリリソースを回収するゴミ回収器があります.しかし、gcはnewキーワードデシベルを使用するメモリしか回収できず、他の方法のメモリ割り当てに対しては、gcは何もできません.この場合に対応するためにjavaはクラスでfinalize()メソッドを定義できます.その動作原理は、gcがオブジェクトのメモリ領域を解放する準備ができたら、まずfinalize()メソッドを呼び出し、次のゴミ回収動作が発生したときに、オブジェクトが消費するメモリを本当に回収することである.しかし、実際のアプリケーションでは、ゴミ回収時にのみ実行されるため、finalize()に依存してクリーンアップ作業を完了することはできません.では、いつgcが実行されますか?必ずしもそうではないし、プログラム終了時にも実行されない可能性があります.実際にJavaの初期化順序は、次の3つの側面に分けられます.
1. Javaの初期化順序:(静的変数、静的初期化ブロック)>(変数、初期化ブロック)>コンストラクタ 次の例を示します.
出力:静的変数静的初期化ブロック変数初期化ブロックコンストラクタ2.継承を含む場合は親を初期化してから、子クラスを初期化する前の例:
出力:親--静的変数親--静的初期化ブロック子--静的変数子--静的初期化ブロック親--変数親--初期化ブロック親--コンストラクタ子--変数子--初期化ブロック子--コンストラクタ注意:親が完全に初期化されてから子の初期化を行うわけではありません.実際には、サブクラスの静的変数および静的初期化ブロックの初期化は、親クラスの変数、初期化ブロックおよびコンストラクタの初期化前に完了する. 静的変数と静的初期化ブロックとの間、または変数と初期化ブロックとの間の初期化順序は、クラスに現れる前後の順序に依存する. 例もなく真実もない:
出力:Test--A静的初期化ブロックTest-B
1. Javaの初期化順序:(静的変数、静的初期化ブロック)>(変数、初期化ブロック)>コンストラクタ 次の例を示します.
public class InitialOrderTest {
private static String staticField = " ";//
private String field = " "; //
static { //
System.out.println(staticField);
System.out.println(" ");
}
{//
System.out.println(field);
System.out.println(" ");
}
InitialOrderTest() { //
System.out.println(" ");
}
public static void main(String[] args) {
new InitialOrderTest();
}
}
出力:静的変数静的初期化ブロック変数初期化ブロックコンストラクタ2.継承を含む場合は親を初期化してから、子クラスを初期化する前の例:
class Parent {
//
public static String p_StaticField = " -- ";
//
public String p_Field = " -- ";
//
static {
System.out.println(p_StaticField);
System.out.println(" -- ");
}
//
{
System.out.println(p_Field);
System.out.println(" -- ");
}
//
public Parent() {
System.out.println(" -- ");
}
}
public class InitialOrderTest1 extends Parent {
//
public static String s_StaticField = " -- ";
//
public String s_Field = " -- ";
//
static {
System.out.println(s_StaticField);
System.out.println(" -- ");
}
//
{
System.out.println(s_Field);
System.out.println(" -- ");
}
//
public InitialOrderTest1() {
System.out.println(" -- ");
}
//
public static void main(String[] args) {
new InitialOrderTest1();
}
}
出力:親--静的変数親--静的初期化ブロック子--静的変数子--静的初期化ブロック親--変数親--初期化ブロック親--コンストラクタ子--変数子--初期化ブロック子--コンストラクタ注意:親が完全に初期化されてから子の初期化を行うわけではありません.実際には、サブクラスの静的変数および静的初期化ブロックの初期化は、親クラスの変数、初期化ブロックおよびコンストラクタの初期化前に完了する. 静的変数と静的初期化ブロックとの間、または変数と初期化ブロックとの間の初期化順序は、クラスに現れる前後の順序に依存する. 例もなく真実もない:
public class InitialOrderTest2 {
//
public static TestA a = new TestA();
//
static {
System.out.println(" ");
}
//
public static TestB b = new TestB();
public static void main(String[] args) {
new InitialOrderTest2();
}
}
class TestA {
public TestA() {
System.out.println("Test--A");
}
}
class TestB {
public TestB() {
System.out.println("Test--B");
}
}
出力:Test--A静的初期化ブロックTest-B