はじめに
この記事は、Javaを始めたばかりで「The left-hand side of an assignment must be a variable」と表示されて戸惑っている方を対象にしています。
この記事を読むと、
- なぜこのエラーが出るのか(コンパイラの視点)
- よくあるミス三選と即座の修正方法
- エラーメッセージが出ないようにするコーディング習慣
が身につきます。筆者も大学の講義でTAをしていた際、同じ質問を受けたことがきっかけで、体系的にまとめることにしました。
前提知識
- Javaの変数宣言(
int x = 10;レベル) - 四則演算と文字列リテラルの基礎
- IDE(Eclipse/IntelliJ)または
javacコマンドでコンパイルできる環境
エラーの意味:コンパイラが何を怒っているのか
このエラーは、代入演算子=の左側に「値を格納できる場所(変名、フィールド、配列要素)」が来ていない ときに発生します。
Java言語仕様では、代入の左辺を「変数(Variable)」と呼んでおり、単に「名前があれば良い」わけではありません。たとえば、次のコードを見てください。
Javaint a = 5; int b = 2; (a + b) = 10; // ★コンパイルエラー!
(a + b) は一時的な計算結果(右辺値)なので、そこに再び値を上書きしようとすると、コンパイラは「左辺が変数ではない」と判断してエラーを出します。
他の言語(PythonやJavaScript)では「アンパック代入」などで似た書き方ができるものの、Javaにはその概念が存在しません。
実例で学ぶ:3つの典型パターンと修正法
パターン1:メソッド呼び出しの戻り値に代入
Javapublic class Calc { public static int getValue() { return 42; } public static void main(String[] args) { getValue() = 100; // ★エラー } }
修正
戻り値を変数に一旦受けてから扱います。
Javaint result = getValue(); result = 100; // OK
パターン2:文字列連結式を左辺に置く
JavaString prefix = "user"; String suffix = "name"; (prefix + suffix) = "taro"; // ★エラー
修正
連結結果を新しい変数に入れ直します。
JavaString full = prefix + suffix; full = "taro"; // OK
パターン3:比較演算子==を誤って=に書き換え
Javaif (score = 80) { // ★エラー System.out.println("Perfect!"); }
修正
比較は==、代入は別の行で行います。
Javascore = 80; if (score == 80) { ... }
ハマった点:「動的に左辺を作りたい」衝動
初学者のうちは「ユーザーの入力によって代入先を変えたい」として、次のようなコードを書いてしまいがちです。
JavaString varName = "age"; int varName = 30; // 別物の変数宣言になってしまう
変数名を文字列で保持しても、それは単なるデータにすぎません。
この要求を実現するには、
Map<String, Integer>を使う- リフレクションを使う(高度)
の2通りが考えられますが、初学者はMapで十分です。
JavaMap<String, Integer> values = new HashMap<>(); values.put("age", 30); // 代入先を動的に
まとめ
本記事では、「The left-hand side of an assignment must be a variable」エラーの意味と、3つの典型例を紹介しました。
- 代入の左辺に来られるのは「変数(フィールド・配列要素を含む)」のみ
- メソッドの戻り値や計算結果は右辺値なので代入不能
- 変数名を動的にしたいときは
Mapを活用
この知識があれば、今後同エラーに出くわしても即座に修正できます。
次回は「変数のスコープとシャドウイング」について掘り下げていきます。
参考資料
- The Java Language Specification, §15.26 Assignment Operators
- Eclipse エラーメッセージ一覧 - Java Build Errors
- 山田祥典『Javaプログラミング入門 第3版』(技術評論社, 2022)
