値が変わらないときに疑う変数の隠蔽
同名のローカル変数がフィールドを覆い隠します。コンストラクタで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 を (空) にします。
パターン4
1 public class Main { 2 int total = 100; 3 void addAll(int[] nums) { 4 int total = 0; ^ 5 for (int n : nums) total += n; 6 } 7 public static void main(String[] args) { 8 Main m = new Main(); 9 m.addAll(new int[]{1, 2, 3}); 10 System.out.println(m.total); 11 } 12 }
出力: 100期待: 6 (コンパイルは通っています)
型を書くとローカル変数total が新しく作られ、フィールドのtotalは別物のまま変わりません。
直し方: int を (空) にします。
パターン5
1 public class Main { 2 static int square(int n) { 3 int n = n * n; ^ 4 return n; 5 } 6 public static void main(String[] args) { 7 System.out.println(square(4)); 8 } 9 }
Main.java:3: error: variable n is already defined in method square(int)
引数nはすでにその名前で宣言済みです。値を更新するだけなら型を書かずに代入します。
直し方: int を (空) にします。
よくある誤解
エラーも警告も出ません。「値が変わらない」という症状だけが残るので、原因にたどり着きにくい種類のバグです。
実務での勘所
コンストラクタの引数にフィールドと同じ名前を使うこと自体は、実務でもよく使われる意図的な書き方です(むしろ推奨されることが多いスタイルです)。問題になるのは、意図的に同じ名前にしたのにthis.を付け忘れて代入文を書いてしまう場合だけです。javac自体はこのミスを警告しませんが、IntelliJ IDEAやEclipseの静的解析は「フィールドを隠蔽している」という警告を出すことが多いので、IDEの警告表示をオフにしていないか確認する価値があります。