cannot assign a value to final variable の原因と直し方
finalが固定するのは参照であって中身ではありません。final / static final の違いを整理します。
エラーメッセージの読み方
Main.java:4: error: cannot assign a value to final variable LIMIT
Main.java- ファイル名
4- 行番号 — javacが異常に気づいた位置。原因の行とは限りません
error- 種別 — コンパイルエラー。実行まで到達しません
cannot assign a value to final variable LIMIT- 内容 — javacが期待していたもの、または見つけられなかったもの
このエラーが出る典型パターン
パターン1
1 public class Main { 2 public static void main(String[] args) { 3 final int LIMIT = 10; 4 LIMIT = 20; ^ 5 System.out.println(LIMIT); 6 } 7 }
finalは1度しか代入できません。定数として使うなら宣言と同時に初期化し、以後は再代入しません。
直し方: LIMIT = 20; を (空) にします。
パターン2
1 import java.util.ArrayList; 2 import java.util.List; 3 4 public class Main { 5 public static void main(String[] args) { 6 final List<String> list = new ArrayList<>(); 7 list = new ArrayList<>(); ^ 8 System.out.println(list); 9 } 10 }
finalが固定するのは参照であって中身ではありません。要素の追加や削除は自由にできます。
直し方: list = new ArrayList<>() を list.add("a") にします。
パターン3
1 public class Main { 2 static final int ID; ^ 3 Main(int id) { this.ID = id; } 4 public static void main(String[] args) { 5 System.out.println(new Main(7).ID); 6 } 7 }
static finalはクラス単位の定数なのでコンストラクタで代入できません。インスタンスごとに固定するならfinalのみです。
直し方: static final を final にします。
パターン4
1 public class Main { 2 static int square(final int n) { 3 n = n + 1; ^ 4 return n * n; 5 } 6 public static void main(String[] args) { 7 System.out.println(square(4)); 8 } 9 }
finalが付いた引数は再代入できません。同じ意味の別変数が必要なら新しいローカル変数を宣言します。
直し方: n = n + 1; を (空) にします。
パターン5
1 public class Main { 2 final int id; 3 Main(int id) { this.id = id; } 4 Main() { } ^ 5 public static void main(String[] args) { 6 System.out.println(new Main().id); 7 } 8 }
finalフィールドはすべてのコンストラクタで必ず初期化しなければなりません。1つでも代入し忘れると、そのコンストラクタでコンパイルエラーになります。
直し方: (空) を this.id = 0; にします。
よくある誤解
finalなListの中身は変えられます。本当に不変にしたいなら List.of を使ってください。
実務での勘所
finalが保証するのは「この変数に別のオブジェクトを再代入できない」ことだけで、「そのオブジェクトの中身が変更できない」こととは別の話です。真に中身も変更できないイミュータブルなオブジェクトにしたい場合は、finalを付けることに加えて、そのクラス自体が状態を変更する手段(setterなど)を持たない設計にする必要があります。StringやIntegerのようなラッパー型が安全に共有できるのは、finalだからではなく、クラス自体がイミュータブルに設計されているためです。