instance field の initialize のタイミング

今日は以下のようなコードで表されるバグで死んだ。
まず親クラス。


abstract public class parent {

public parent() {
init();
}

abstract public void init();

}

つづいて子クラス。

public class child extends parent {

private int value = 100;

public child() {
super();
}

public void init() {
value = 300;
}

public void printValue() {
System.out.println("value is "+value);
}

public static void main(String[] argv) {
new child().printValue();
}
}

単純に考えると、child のコンストラクタで init メソッドが呼ばれて、value が 300 になり、それを printValue メソッドで出力するので 300 が出力されると思う。


だが実際には 100 が出力されるのである。


これは分かってみると単純なことで、一番簡単に言うと親クラスの構築(constractor)が終わらないのに子クラスの初期化が行えるわけがない。ということである。親クラスの初期化が終わったので子クラスの初期化が行われる。その際に value に 100 が設定される。そのため printValue 時には 100 が出力される。


教訓:
final でない instance field に宣言時に値を代入しないこと。