jvm static変数のクラス順序を初期化

1388 ワード


 class Nolization{
	static{
		System.out.println("Nolization init");
	}

	public static int  value = 123;
}

 class Contant extends Nolization{

	static{
		System.out.println("Contant init");
	}
}

public class ContantClass {
	public static void main(String[] args) {
		System.out.println(Contant.value);
	}
}

上のコードの実行結果はNolization initです
123
Contant initは出力されません.これは、jvmが静的フィールドに対して、このフィールドを直接定義するクラスのみが初期化されるためです.
次のコードを見てみましょう

  class Nolization{
	static{
		System.out.println("Nolization init");
	}

	public static final int  value = 123;
}

 class Contant extends Nolization{

	static{
		System.out.println("Contant init");
	}
}

public class ContantClass {
	public static void main(String[] args) {
		System.out.println(Contant.value);
	}
}

上段コードに比べてvalueをpublic static intからpublic static finalintに変更するだけで、出力の結果は123となり、クラスの初期化情報は出力されません.
これは、jvmがコンパイル段階で定数123をContantClassの定数プールに格納、Contant.valueの参照は実際にはContantClassの自己定数への参照に変換されます.つまり、ContantClassのclassファイルにはNolizationの呼び出しエントリは存在しません.classファイルにコンパイルした後、この2つのバイトコードファイルには何のつながりもありません.