Java の初期化の順番

なんとなく気になったので実験してみた

public class Test {

	static{
		System.out.println("---" + Test.class.getName() + " : main の初期化ここから");
	}
	static Hoge hoge = new Hoge();
	static{
		System.out.println("---" + Test.class.getName() + " : main の初期化ここまで");
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("--- main の処理ここから");
		Hoge hoge = new Hoge();
		System.out.println("--- main の処理ここまで");
		
	}
	static class Hoge{
		
		static Bar bar1 = new Bar("bar1 - static");
		Bar bar2 = new Bar("bar2");
		
		static{
			System.out.println(Hoge.class.getName() + " : スタティックイニシャライザだよ♪");
		}
		{
			System.out.println(Hoge.class.getName() + " : インスタンスイニシャライザだよ♪");
		}
		static Bar bar3 = new Bar("bar3 - static");
		Bar bar4 = new Bar("bar4");
		Hoge(){
			System.out.println(Hoge.class.getName() + " : コンストラクタだよ♪");
		}
	}
	static class Bar{
		Bar(String text){
			System.out.println(Bar.class.getName() +  " : コンストラクタだよ♪ : " + text);
		}
	}
}

結果

yoshiori@yoshiori-ubuntu $ java Test
---Test : main の初期化ここから
Test$Bar : コンストラクタだよ♪ : bar1 - static
Test$Hoge : スタティックイニシャライザだよ♪
Test$Bar : コンストラクタだよ♪ : bar3 - static
Test$Bar : コンストラクタだよ♪ : bar2
Test$Hoge : インスタンスイニシャライザだよ♪
Test$Bar : コンストラクタだよ♪ : bar4
Test$Hoge : コンストラクタだよ♪
---Test : main の初期化ここまで
--- main の処理ここから
Test$Bar : コンストラクタだよ♪ : bar2
Test$Hoge : インスタンスイニシャライザだよ♪
Test$Bar : コンストラクタだよ♪ : bar4
Test$Hoge : コンストラクタだよ♪
--- main の処理ここまで

なんというか普通に普通だった。

  • 最初にスタティックな変数宣言とスタティックイニシャライザを記載した順番どおりに初期化
  • 次にインスタンス変数とインスタンスイニシャライザを記載した順番どおりに初期化
  • 次に自身のコンストラクタ
  • スタティックな変数宣言とスタティックイニシャライザは最初に呼びだされた一度のみ実行