はじめに

この記事は、Javaを始めたばかりで「The left-hand side of an assignment must be a variable」と表示されて戸惑っている方を対象にしています。
この記事を読むと、

  • なぜこのエラーが出るのか(コンパイラの視点)
  • よくあるミス三選と即座の修正方法
  • エラーメッセージが出ないようにするコーディング習慣

が身につきます。筆者も大学の講義でTAをしていた際、同じ質問を受けたことがきっかけで、体系的にまとめることにしました。

前提知識

  • Javaの変数宣言(int x = 10;レベル)
  • 四則演算と文字列リテラルの基礎
  • IDE(Eclipse/IntelliJ)またはjavacコマンドでコンパイルできる環境

エラーの意味:コンパイラが何を怒っているのか

このエラーは、代入演算子=の左側に「値を格納できる場所(変名、フィールド、配列要素)」が来ていない ときに発生します。
Java言語仕様では、代入の左辺を「変数(Variable)」と呼んでおり、単に「名前があれば良い」わけではありません。たとえば、次のコードを見てください。

Java
int a = 5; int b = 2; (a + b) = 10; // ★コンパイルエラー!

(a + b) は一時的な計算結果(右辺値)なので、そこに再び値を上書きしようとすると、コンパイラは「左辺が変数ではない」と判断してエラーを出します。
他の言語(PythonやJavaScript)では「アンパック代入」などで似た書き方ができるものの、Javaにはその概念が存在しません。

実例で学ぶ:3つの典型パターンと修正法

パターン1:メソッド呼び出しの戻り値に代入

Java
public class Calc { public static int getValue() { return 42; } public static void main(String[] args) { getValue() = 100; // ★エラー } }

修正
戻り値を変数に一旦受けてから扱います。

Java
int result = getValue(); result = 100; // OK

パターン2:文字列連結式を左辺に置く

Java
String prefix = "user"; String suffix = "name"; (prefix + suffix) = "taro"; // ★エラー

修正
連結結果を新しい変数に入れ直します。

Java
String full = prefix + suffix; full = "taro"; // OK

パターン3:比較演算子==を誤って=に書き換え

Java
if (score = 80) { // ★エラー System.out.println("Perfect!"); }

修正
比較は==、代入は別の行で行います。

Java
score = 80; if (score == 80) { ... }

ハマった点:「動的に左辺を作りたい」衝動

初学者のうちは「ユーザーの入力によって代入先を変えたい」として、次のようなコードを書いてしまいがちです。

Java
String varName = "age"; int varName = 30; // 別物の変数宣言になってしまう

変数名を文字列で保持しても、それは単なるデータにすぎません。
この要求を実現するには、

  • Map<String, Integer>を使う
  • リフレクションを使う(高度)

の2通りが考えられますが、初学者はMapで十分です。

Java
Map<String, Integer> values = new HashMap<>(); values.put("age", 30); // 代入先を動的に

まとめ

本記事では、「The left-hand side of an assignment must be a variable」エラーの意味と、3つの典型例を紹介しました。

  • 代入の左辺に来られるのは「変数(フィールド・配列要素を含む)」のみ
  • メソッドの戻り値や計算結果は右辺値なので代入不能
  • 変数名を動的にしたいときはMapを活用

この知識があれば、今後同エラーに出くわしても即座に修正できます。
次回は「変数のスコープとシャドウイング」について掘り下げていきます。

参考資料