値が変わらないときに疑う変数の隠蔽
同名のローカル変数がフィールドを覆い隠します。コンストラクタでthis.が必要な理由を扱います。
なぜエラーが出ないのか
出力: 10
(エラーなし)- javacは何も報告しません。文法として正しいためです
出力: 10- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 public class Main { 2 static int count = 10; 3 4 static void reset() { 5 int count = 0; ^ 6 } 7 public static void main(String[] args) { 8 reset(); 9 System.out.println(count); 10 } 11 }
出力: 10期待: 0 (コンパイルは通っています)
型を書くとローカル変数が新しく作られ、フィールドは変わりません。これを変数の隠蔽と呼びます。
直し方: int を (空) にします。
広告
広告スロット(未設定)
パターン2
1 public class Main { 2 int value; 3 4 Main(int value) { 5 value = value; ^ 6 } 7 public static void main(String[] args) { 8 System.out.println(new Main(5).value); 9 } 10 }
出力: 0期待: 5 (コンパイルは通っています)
引数とフィールドが同名のとき、引数が優先されます。フィールドを指すにはthis.が要ります。
直し方: (空) を this. にします。
パターン3
1 public class Main { 2 public static void main(String[] args) { 3 int sum = 0; 4 for (int i = 0; i < 3; i++) { 5 int sum = sum + i; ^ 6 } 7 System.out.println(sum); 8 } 9 }
Main.java:5: error: variable sum is already defined in method main(String[])
ループの中で同名を再宣言すると、外側と衝突します。集計用の変数はループの外で1回だけ宣言します。
直し方: int を (空) にします。
よくある誤解
エラーも警告も出ません。「値が変わらない」という症状だけが残るので、原因にたどり着きにくい種類のバグです。
まとめ
値が変わらないときに疑う変数の隠蔽は中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。