【Java】初期化ブロックについて

スポンサーリンク

初期化ブロックとstatic初期化ブロックについて使い方と実行順序をまとめました。

初期化ブロック(オブジェクトイニシャライザ)

オブジェクトの初期化を行うための仕組みに初期化ブロックがあり、インスタンスの生成時に実行されます。復数の初期化ブロックがある場合はコードに書かれた順に実行されます。

import java.util.Date;

public class InitializerSample {
    private final Date date;
    {  // 初期化ブロック
        System.out.println("初期化ブロックの実行");
        date = new Date();
    }
    public Date getDate() {
        return date;
    }
    public static void main(String[] args) {
        InitializerSample init = new InitializerSample();
        System.out.println(init.getDate().toString());
    }
}

実行結果は以下の通りです。通常 final 付きの変数は宣言と同時に初期化するか、コンストラクタで初期化する必要がありますが、初期化ブロックもコンストラクタと同じなので可能です。

$ java InitializerSample
初期化ブロックの実行
Mon Oct 12 00:16:03 JST 2015

初期化ブロックの役割はコンストラクタとほぼ同じなので必要性はあまりないですが、用途は主に次の2つです。

  • すべてのコンストラクタの共通処理を記述可能
  • 匿名クラスの初期化に使用(匿名クラスにはコンストラクタがないため)

以下のように Map を匿名クラスで宣言と同時に初期化したい時にも使えます。が、この場合はダイアモンド演算子が使えないので型引数が省略できません。

Map<String, String> map = new HashMap<String, String>() {
    {
        put("key1","value1");
        put("key2","value2");
    }
};

 HashMap Construction with initial values (Java in General forum at JavaRanch)

static初期化ブロック(staticイニシャライザ)

オブジェクト用の初期化ブロックと同様の仕組みとして、クラス用に static 初期化ブロックがあり、クラス自身の初期化時に実行されます。オブジェクトの初期化時ではありません。復数の static 初期化ブロックをがある場合はコードに書かれた順に実行されます。

import java.util.Date;

public class InitializerSample {
    public static final Date DATE;
    static {  // static初期化ブロック
        System.out.println("static初期化ブロックの実行");
        DATE = new Date();
    }
    public static void main(String[] args) {
        System.out.println(DATE.toString());
    }
}

実行結果は以下の通りです。通常 static 変数は宣言と同時に初期化しますが、static初期化ブロックで初期化することも可能です。

$ java InitializerSample
static初期化ブロックの実行
Mon Oct 12 00:16:03 JST 2015

static 初期化ブロックはクラス初期化時のみに実行されるため、インスタンスメンバや this 参照を記述するとコンパイルエラーになります。

初期化処理の順序

初期化処理は次の順序で実行されます。

  1. フィールド変数にデフォルト値代入
  2. static初期化ブロックを上から順に実行
  3. 初期化ブロックを上から順に実行
  4. コンストラクタの呼び出し
class SuperClass {
    public static final String STATIC_INIT = "static初期化ブロック";
    public static final String OBJECT_INIT = "初期化ブロック";
    static {
        System.out.println("スーパークラスの" + STATIC_INIT + "の実行");
    }
    {
        System.out.println("スーパークラスの" + OBJECT_INIT + "の実行");
    }
    public SuperClass() {
        System.out.println("スーパークラスのコンストラクタ実行");
    }
}

public class InitializerSample extends SuperClass {
    static {
        System.out.println("サブクラスの" + STATIC_INIT + "の実行");
    }
    {
        date = new Date();
        System.out.println("サブクラスの" + OBJECT_INIT + "の実行");
    }
    public InitializerSample() {
        System.out.println("サブクラスのコンストラクタの実行");
    }
    public static void main(String[] args) {
        InitializerSample init = new InitializerSample();
        System.out.println("mainメソッドの実行");
    }
}

実行結果は以下の通りです。

$ java InitializerSample
スーパークラスのstatic初期化ブロックの実行
サブクラスのstatic初期化ブロックの実行
スーパークラスの初期化ブロックの実行
スーパークラスのコンストラクタ実行
サブクラスの初期化ブロックの実行
サブクラスのコンストラクタの実行
mainメソッドの実行