Java : 初期化ブロック
気になったので、調査してみました。
public class Main { static class Test { { num = 0; /*p(num);*/} //コンパイルエラー int num = num(); Test() { num = 1; p(num);} { num = 2; p(num);} int num() { p(3); return 3;} { num = 4; p(num);} } public static void main(String[] args) { Test test = new Test(); System.out.println(test.num); } static void p(int num) { System.out.println(num);} }
3行目のコメントアウトは、「順方向参照が不正です。」というエラーメッセージでコンパイルできなかったところです。
実行結果は、
3 2 4 1 1
ということで、まず、フィールドの初期化メソッドが呼ばれて、次に初期化ブロックが上から順に呼ばれ、最後にコンストラクタが呼ばれているみたい。
じゃあ、ということで、こんな風に追加すると、
public class Main { static class Test { { num = 0; /*p(num);*/} //コンパイルエラー int num3 = num3(); int num = num(); Test() { num = 1; p(num);} { num = 2; p(num);} int num2() { num = 5; p(num); return num;} int num() { p(3); return 3;} { num = 4; p(num);} int num2 = num2(); int num3() { num = 6; p(num); return num;} } public static void main(String[] args) { Test test = new Test(); System.out.println(test.num); } static void p(int num) { System.out.println(num);} }
結果は、
6 3 2 4 5 1 1
フィールドの初期化メソッドは、一番最初に上から順に呼ばれている。
サブクラスはどうかと確認してみると、
public class Main { static class Test { int num = num(); Test() { num = 1; p(num);} { num = 2; p(num);} int num() { p(3); return 3;} { num = 4; p(num);} } static class SubTest extends Test { { num = 5; p(num);} } public static void main(String[] args) { Test test = new SubTest(); System.out.println(test.num); } static void p(int num) { System.out.println(num);} }
3 2 4 1 5 5
サブクラスの初期化ブロックは、一番最後に呼ばれている。
ふむ。納得。