Re:インスタンス変数の初期化タイミングとか
インスタンス変数の初期化タイミングとか
http://d.hatena.ne.jp/cocoon1982/20120515/1337049129
アンサーソングをばw
お題
クラス内に、何も修飾せず「{ 実装 }」と記述することで、コンストラクタが呼び出される前にメソッドとして呼び出される。はずなのに、
動作としてはClassB()からClassA()、ここまではいい。その時点でa = null;されて、そこからinitialize()、overrideしてるからここではClassBのinitialize()が呼ばれて、b = "b";。その後、ClassB()のsuper()に戻ってきてb = nullされる。つまりString b = null;のb = null先にinitialize()のb = "b";が動いてるって事らしい。スーパークラスのコンストラクタの
b = "b";
の後にサブクラスの
b = null;
が動くのが納得行かない。
確かにそっすね。
結論から言いますと、
『サブクラスの、スーパークラス初期化のエントリポイントが、コンストラクタじゃなくって、インスタンス初期化子の先頭だったら気持ち悪く無かったかもしれない。』
ということになるでしょうか。
バイトコードを見てみましょう
継承関係を絡めた、コンストラクタ、各種初期化子の実行順ってよく話題になりますね。
もちろん、OJC-Pの問題集にもありました。
今回は、こまけえこた(ryってことで、バイトコードを見てみるおw
javapじゃなくってBytecode Outline plugin for Eclipse使います。
サブクラスのコンストラクタのsuper()を省略
サブクラスのコンストラクタの先頭からスーパークラスのコンストラクタ
↓
サブクラスのインスタンス(変数)初期化
↓
サブクラスのコンストラクタのコード
実行順は同じですね。
インスタンス初期化子版
サブクラスのコンストラクタの先頭super()からスーパークラスのコンストラクタ
↓
サブクラスのインスタンス(変数)初期化
↓
サブクラスのコンストラクタのコード
これも、実行順は同じですね。
あと、「インスタンス初期化子」のブロックは、さっきまでの「インスタンス変数の宣言と同時に初期化」と全く同じになってます。
ちなみに、インスタンス初期化子は、JUnitのテストケースなんかで、データを準備する時にちょっと便利です。
HashMap<String, String> m = new HashMap<String, String>() { { put("A", "あ"); put("B", "い"); } };