static フィールドの初期化順序
宣言順に初期化されます。static初期化ブロックとインスタンス初期化ブロックの違いも扱います。
なぜエラーが出ないのか
出力: 1
(エラーなし)- javacは何も報告しません。文法として正しいためです
出力: 1- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 public class Main { 2 static int a = Main.b + 1; 3 static int b = 2; 4 public static void main(String[] args) { 5 System.out.println(a ); ^ 6 } 7 }
出力: 1期待: 3 (コンパイルは通っています)
staticフィールドは書いた順に初期化されます。まだ0のbを使ってaが計算されます。
直し方: a を b にします。
広告
広告スロット(未設定)
パターン2
1 public class Main { 2 static int count; 3 { count = 10; } ^ 4 public static void main(String[] args) { 5 System.out.println(count); 6 } 7 }
出力: 0期待: 10 (コンパイルは通っています)
staticを付けない初期化ブロックはインスタンス生成時にしか動きません。mainからは実行されません。
直し方: (空) を static にします。
パターン3
1 public class Main { 2 static final int LIMIT; 3 { LIMIT = 5; } ^ 4 public static void main(String[] args) { 5 System.out.println(LIMIT); 6 } 7 }
Main.java:3: error: cannot assign a value to final variable LIMIT
static finalは宣言時かstatic初期化ブロックでのみ代入できます。インスタンス初期化ブロックからの代入は許されません。
直し方: (空) を static にします。
よくある誤解
宣言の順番を入れ替えるだけで挙動が変わります。しかもエラーは出ません。
まとめ
static フィールドの初期化順序は上級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。