【Java】初期化について
はじめに
Javaのとある書籍を読んでいて、学んだことがあったので備忘録がてらエントリする。今回は、フィールドのstatic初期化について記載する。
サンプルプログラム
今回の例では、2つのクラスを用意し、それぞれがもう片方のstatic初期化をしようとすると、どんな手順で初期化が行われるのかを記載する。【ClassA.java】
public class ClassA { static int x = ClassB.init(); static int init() { return x; } }
【ClassB.java】
public class ClassB { static int y = ClassA.init(); static int init() { return y+=10; } }
このコードでやっていること
見てのとおり、各クラスのフィールドの初期化である。しかし、この場合、互いのフィールドは互いのクラスのinitメソッドを使って初期化しようとしている。この場合、互いのフィールドに格納される値は何なのだろうか。【前提】 1. メソッド実行の前に初期化が実行されることが保障されている。 2. 初期化は1度だけ行われる。
上記前提を踏まえたうえで、処理の流れを追っていく。
今回記したコードの場合、以下の手順で処理が進む。
- x の値の初期化が始まる。
- ClassB #init() が呼ばれる。 ※呼ばれるものの、ClassB #init()は実行されない。なぜなら、ClassBの初期化がされていないから。
- ClassB の初期化のために、ClassA.init() が呼ばれる。
- ClassA #init() 内に処理が進む。xをリターンするとあるが、xはまだ初期化されていない。この場合、デフォルト値である0がリターンされる。
- ClassA #init() のリターン値「0」がClassB.yに格納される。つまり、「ClassB.y = 0」で初期化される。
- ClassBの初期化が終わったので、ClassAの初期化が可能になる。=ClassAの初期化のために呼ばれていたClassB #init()が実行される。
- ClassB #init() のリターン値は、ClassBのフィールド値yに10を足した値。y=0でなので、10がリターンされる。
- ClassA.xに、ClassB #init() のリターン値が格納される。つまり、「ClassA.x = 10」で初期化される。
まとめ
各クラスのフィールドが、互いのクラスのstaticメソッドで初期化されるときの処理を追っていった。実際のコードでこのようなややこしい(面倒くさい)初期化をすることはそうそう無いとは思うが、初期化の順序というか、流れは知っておいて損は無いと思う。
コンストラクタや初期化ブロックといったフィールドの初期化方法がJavaには備わっている。近々これについても投稿できればと思う。