[Java]インスンタンス初期化ブロックと静的初期化ブロック

わかりやすいJava_オブジェクト指向編を読んで勉強中。。

初期化ブロック

初期化ブロックは 名前の通り 初期化を行うためのブロック。

インスタンス初期化ブロックと静的初期化ブロックがあり、実行されるタイミングが異なる。

インスタンス初期化ブロック

public class InitializationBlockTest {

  public static void main(String[] args) {
    System.out.println("Main関数呼び出し");
    new InitializationBlockTest();
    System.out.println("Main関数終了");
  }

  public InitializationBlockTest() {
    System.out.println("コンストラクタ");
  }

  {
    // 初期化ブロック
    System.out.println("インスタンス初期化ブロック");
    // インスタンス生成時に実行される。
    // コンストラクタよりも先に実行される。
  }

  {
    System.out.println("インスタンス初期化ブロックその2");
    // 初期化ブロックはいくつでも書ける
  }

  static {
    // 静的初期化ブロック
    System.out.println("静的初期化ブロック");
    // クラスが初めて利用されるときに実行される。
  }

  static {
    System.out.println("静的初期化ブロックその2");
  }
}

結果

静的初期化ブロック
静的初期化ブロックその2
Main関数呼び出し
初期化ブロック
初期化ブロックその2
コンストラクタ
Main関数終了

インスタンス初期化ブロックはコンストラクタと機能的には大差ないんだけど、コンストラクタは複数存在している内のひとつを利用するのに対して、初期化ブロックはすべてのインスタンス生成時に必ず実行される。要するにどのコンストラクタでも実行するような初期化処理をインスタンス初期化ブロックに切り出すと楽ですよって感じかな。

継承時の呼び出し順

package jp.fernweh;

public class Child extends Parent {

  public static void main(String[] args) {
    System.out.println("Main関数呼び出し");
    new Child();
    System.out.println("Main関数終了");
  }

  public Child() {
    System.out.println("Child  : コンストラクタ");
  }

  {
    System.out.println("Child  : インスタンス初期化ブロック");
  }

  static {
    System.out.println("Child  : 静的初期化ブロック");
  }
}

class Parent {

  public Parent() {
    System.out.println("Parent : コンストラクタ");
  }

  {
    System.out.println("Parent : インスタンス初期化ブロック");
  }

  static {
    System.out.println("Parent : 静的初期化ブロック");
  }
}

結果

Parent : 静的初期化ブロック
Child  : 静的初期化ブロック
Main関数呼び出し
Parent : インスタンス初期化ブロック
Parent : コンストラクタ
Child  : インスタンス初期化ブロック
Child  : コンストラクタ
Main関数終了

コンストラクタと同様、初期化ブロックはオーバーライドされたりせず、また親の初期化ブロックが先に実行される。

こんなキモい使い方もあるそうな

  • Javaの匿名クラスを使ってかっこよくオブジェクトを初期化するテクニック - 矢野勉のはてな日記 ttp://d.hatena.ne.jp/t_yano/20080622/1214087678 (リンク切れ)
  • Listとか - YoshioriのBlog

お~こんな書き方があるのか。。

List<String> a = Arrays.asList("1", "2", "3");
List<String> b = new ArrayList<String>(a);

// serial verision ID をつけろと警告が出てしまう…
final List<String> c = new ArrayList<String>(){{
   add("a"); add("b"); add("c");
}};

class Foobar {
    public String foobar;
}

Foobar hoge = new Foobar(){{
 foobar = c.get(0);
}};

System.out.println(hoge.foobar);

Serializable実装してると警告が出るのがちょっと嫌だな…

Share
関連記事