マイナー・マイナー

隠れた名作の発掘が生きがい。

static初期化子,インスタンス初期化子,コンストラクタの実行順序


スポンサードリンク

クラスにはstatic初期化子(staticイニシャライザ),インスタンス初期化子(インスタンスイニシャライザ),コンストラクタが定義できます.それらはインスタンス生成時に行いたい処理を記述することができますが,実行するタイミングが違うため注意が必要です.それらの実行のタイミングは次の通りです.

コード 実行のタイミング
static初期化子 クラスのロード時
インスタンス初期化子 インスタンス生成前
コンストラクタ インスタンス生成後


static初期化子はクラスのロード時に一度だけ呼ばれるだけなので,インスタンスを複数生成する場合,インスタンスは最初のひとつの生成時にしかstatic初期化子は呼ばれません.しかし,インスタンス初期化子とコンストラクタは毎回呼び出されます.


クラスに上記のコードを記述した場合,(1)static初期化子,(2)インスタンス初期化子,(3)コンストラクタの順番に呼び出されます*1.また,このクラスを継承したサブクラスを定義し,そのサブクラスにさらに上記のコードを記述した場合,次の順序で実行されます.(サブクラスのインスタンス初期化子よりも先にスーパークラスのコンストラクタが呼び出されます)
(1)スーパークラスのstatic初期化子
(2)サブクラスの初期化子
(3)スーパークラスインスタンス初期化子
(4)スーパークラスのコンストラクタ
(5)サブクラスのインスタンス初期化子
(6)サブクラスのコンストラクタ


上記のことを確認するために,次のようなプログラムを作成しました.実行順序と,static初期化子は一度しか実行されないことが分かりました.

class InitializerSuper {
	//スーパークラスのstatic初期化子
	static {
		System.out.println("A");
	}

	//スーパークラスのインスタンス初期化子
	{
		System.out.println("C");
	}

	//スーパークラスのコンストラクタ
	public InitializerSuper() {
		System.out.println("D");
	}
}

class InitializerSub extends InitializerSuper {

	//サブクラスのstatic初期化子
	static {
		System.out.println("B");
	}

	//サブクラスのインスタンス初期化子
	{
		System.out.println("E");
	}

	//サブクラスのコンストラクタ
	public InitializerSub() {
		System.out.println("F");
	}
}

public class InitializerTest {

	public static void main(String[] args) {

		System.out.println("first");
		InitializerSub initializer1 = new InitializerSub();
		System.out.println("second");
		InitializerSub initializer2 = new InitializerSub();
	}
}


実行結果


first
A
B
C
D
E
F
second
C
D
E
F

*1:一概には言えないようです.この記事のコーディング例のようなプログラムのみ当てはまります.2011/8/14