イニシャライザとは
クラスのロード時やinstant時にフィールドを初期化したりするために使うものです。
ロード時がstaticイニシャライザ(以下、static{})でinstant時がイニシャライザ(以下、{})を用います。
この2つのみ(JavaGoldまでの範囲では)なのですが順番や呼び出しがややこしかったので、
振り返り用にまとめました。
基本的なコードと解説
class Foo{
//イニシャライザ
{System.out.print("A");}
//コンストラクタ
Foo() {System.out.print("B");}
}
class Test{
//staticイニシャライザ
static {System.out.print("C");}
//main()
public static void main(String[] args){
//インスタンス化
Foo foo = new Foo();
}
}
(見辛いと思い、クラスとmain()のみ改行してます。逆に見辛かったらすみません。)
実行結果です
CAB
解説
static{}はクラスのロード時に読み込まれるため、main()のあるTestクラスの”C”が最初に出力されます。次にmain()でFooクラスを生成しています。
この時、constructorよりも先に{}が呼び出され、次にconstructorが呼ばれます。
従って順番は”CAB”となります。
ややこしめのコードと解説
class Foo{
{System.out.print("A");}
Foo() {System.out.print("B");}
}
class Bar{
//フィールド
static int i = 1;
//イニシャライザ
{System.out.print("D");}
//staticイニシャライザ
static {System.out.print("C");}
//コンストラクタ
Bar() {System.out.print("E");}
}
class Test{
//main()
public static void main(String[] args){
//Fooクラスのインスタンス化
Foo foo = new Foo();
//Barクラスの変数iを出力
System.out.print(Bar.i);
//Barクラスのインスタンス化
Bar bar = new Bar();
}
}
こちらが実行結果になります。
ABC1DE
解説
最初のmain()の1行目では前述した基本的なコードと同じく、”AB”が出力されます。
2行目のBarの変数iの出力ですが、変数iはstaticであるため生成は必要ありません。そして処理を行おうとすると、出力の前にstatic{}が実行されます。したがって、”C1”の順で出力されているのがわかります。
その後、Barクラスを生成し{}とconstructorの処理を行い”DE”と出力されます。この時static{}は1度出力されているため、新たに生成しようが処理はされません。
加えて
Barクラスの変数iの出力文を削除して実行するとABCDEとなります。コードの順番的にはstatic{}が後なのですが、実行順は{}が後になります。
最後に
僕がこのコードで最初に疑問だったのは、
static{}はmain()とは別のクラスにある場合、最初にロードされないのか?
といったものでした。結果的にクラスが読み込まれるのは呼び出された時なのかぁ
と気づけたのもよかったです。
追記
イニシャライザのことで書き忘れてたのを書いてきます。
・Interfaceでのイニシャライザの記述はコンパイルエラーです。(おそらく)
→書けた方がいましたらコメント共有頂けると有難いです。
・イニシャライザに関して。イニシャライザを持つ親クラスを継承した子クラスをmain()で
生成した際に、子クラスから親クラスのコンストラクタを呼び出しますが、その際にもイニシャライザ
が実行されます。