4.8 静的初期化子
4.8.1 クラスの初期化
コンストラクタはインスタンスを初期化するために呼び出されるものなので、static フィールドを初期化することはできません。クラス変数の初期化は変数初期化子で行うことができましたが、この場合は 1 つの式文で表現できる範囲でなければなりません。複雑なクラス変数の初期化はどうすればよいのでしょう。
この問題は、クラスそのものを初期化するための静的初期化子というブロックを記述することで解決することができます。静的初期化子は、クラスが生成される時に呼び出される、クラスのためのコンストラクタ的存在です。クラスが生成される時とは、仮想マシンが何らかのコードの働きかけからクラスが必要になり、バイトコードがメモリにロードされた時です。逆に、どのコードからもクラスに対するアクセスがなければ、クラスは生成されません。静的初期化子は次のように記述します。
static { 本文 }
静的初期化子は、static キーワードとそれに続くブロックから構成されます。必ず、クラスの中で宣言されなければなりません。フィールドやメソッドなどと同様に、記述する位置は問われません。複数の静的初期化子を 1 つのクラスの中で指定することも可能です。この場合、必ず上から順に実行されます。
ブロックの中には文を自由に記述することができますが、唯一 return 文を記述することができない点で通常のメソッドのブロックと異なります。return 文が発見された場合はコンパイル・エラーとなります。当然、静的初期化子のブロックは静的コンテキストなので this を記述することはできません。
class Kitty { static { System.out.println("Kitty on your lap"); } } class Test { static { System.out.println("Test class front "); } public static void main(String args[]) { Kitty obj = new Kitty(); } static { System.out.println("Test class back"); } }
>java Test Test class front Test class back Kitty on your lap
コード1は静的初期化子の働きをよく表しています。静的初期化子はクラスが仮想マシンによって読み込まれたときに実行されます。当然、最初に読み込まれるクラスは main() メソッドを抱合する Test クラスであり、このクラスの静的初期化子が真っ先に実行されるでしょう。Test クラスは静的初期化子が 2 ヶ所に分散されています。この場合、テキストの上から順に実行されると解釈できます。実行結果を見れば、確かにテキスト上で先に出現している "Test class front" 文字列が先に出力されています。
他にも、このプログラムは Kitty クラスを宣言しています。Test クラスの main() メソッド内で Kitty クラスのインスタンスを生成しているため、クラス・インスタンス生成式が実行された時点で Kitty クラスが Java 仮想マシンによって読み込まれます。もし、main() メソッドで Kitty クラスを参照しなければ、仮想マシンは Kitty クラスを読み込む必要がないため、Kitty クラスの静的初期化子は実行されません。