Javaでのstaticイニシャライザーの呼び出し順について復習がてら試してみました。
普段から、Spring等のフレームワークを使用しているとあまり何がどの順番でよびだされているのか気にしていませんでしたが、気になったので試します。
環境
- java8
今回試すのは、以下のパターンです。
- Mainクラス
- Mainクラスからインスタンスを生成して呼び出されるクラス
- Mainクラスからstaticメソッドを呼び出されるクラス
- それぞれの親クラス
ソース
ソースを確認します。
メインクラス
public class Main {
static {
System.out.println("executeStatic:" + Thread.currentThread().getStackTrace()[1].getClassName());
}
public static void main(String[] args) {
System.out.println("Main実行");
final CalledClass calledClass = new CalledClass();
calledClass.call();
CalledClass2.call();
}
}
インスタンスを生成して呼び出すクラスの親クラス
public class ParentClass {
static {
System.out.println("executeStatic:" + Thread.currentThread().getStackTrace()[1].getClassName());
}
}
インスタンスを生成して呼び出すクラス
public class CalledClass extends ParentClass {
static {
System.out.println("executeStatic:" + Thread.currentThread().getStackTrace()[1].getClassName());
}
public CalledClass() {
super();
}
public void call() {
System.out.println("executeMethod.CalledClass.call");
}
}
staticクラスの親クラス
public class ParentClass2 {
static {
System.out.println("executeStatic:" + Thread.currentThread().getStackTrace()[1].getClassName());
}
}
staticクラス
public class CalledClass2 extends ParentClass2{
static {
System.out.println("executeStatic:" + Thread.currentThread().getStackTrace()[1].getClassName());
}
private CalledClass2() {
super();
}
public static void call() {
System.out.println("executeMethod.CalledClass2.call");
}
}
実行結果
executeStatic:exe.Main
Main実行
executeStatic:exe.ParentClass
executeStatic:exe.CalledClass
executeMethod.CalledClass.call
executeStatic:exe.ParentClass2
executeStatic:exe.CalledClass2
executeMethod.CalledClass2.call
結果
実行結果を見てみると以下のことが分かると思います。
- Javaでは呼び出して必要となったときにクラスインスタンスが作成される。それは、staticメソッドを呼び出す場合もそれは変わらない。
- 子クラスよりも親クラスのインスタンスが先に作成される。当然ですが。
感想
自分の中では、staticクラスはMainの実行よりも早くインスタンスが生成されると思っていましたが、実際は呼び出されるときになって初めて生成されるんですね。
より効率よくメモリを使用しているようで驚きです。