フィールド初期化に関して薀蓄

thisはどこからコレなのか - 西尾泰和のはてなダイアリー
JavaとPythonのフィールド初期化タイミングの違い - 西尾泰和のはてなダイアリー
コメント欄に書いていたら無駄に長くなったので自分のブログに、と。

インスタンス変数に対する初期化式が,そのインスタンス変数の単純名,又は同じクラス内でそのインスタンス変数の右側(つまりソーステキストで後)に宣言が出現する他のインスタンス変数の単純名の使用を含む場合, コンパイル時エラーが発生する。

JavaŒ¾Œê‹K’è ƒNƒ‰ƒX

なので初期化式に単純名 "a" を使用している

public int a = a++;

は仕様どおりエラーです。一方、単純名を使っていない

public int a = this.a++;

は仕様どおりエラーになりません。*1


あと、非 static フィールドの初期化式は という名前の付いたメソッド (≒コンストラクタ) で実行されたりします。

  • そのクラスのソースコード内で,字句的に出現する左から右の順序で,それらの値を対応するインスタンス変数に代入することによって,このクラスに対するインスタンス変数の初期化子を実行する。これらの初期化子の実行が例外となった場合,以降の初期化子は処理しないで,この手順は,同じ例外で中途完了する。そうでなければ,手順5に継続する(ある初期のJava実装では,そのフィールドの初期化子の式が,その型に対するデフォルトの初期値と等しい値をもつ定数式であった場合,コンパイラがそのフィールドを初期化するためのコードを不当に省略していた)。
  • このコンストラクタの残りの本体を実行する。その実行が中途完了した場合,この手順は,同じ理由で中途完了する。そうでなければ,この手順は正常に終了する。
Java言語規定 実行

At the level of the Java virtual machine, every constructor (§2.12) appears as an instance initialization method that has the special name .

Java SE Specifications

なので、実は

class Foo { int a = 123; }

class Foo { int a; Foo() { super(); a = 123; } }

って同じコード吐くんですよ。少なくとも Sun の javac に関して言えば。

*1:仕様どおり、というか、仕様に書いていないどおり、というか