HOWTO · Java

Java の `<identifier> expected` エラーを修正する方法

javac が示す `<identifier> expected` の意味と、パラメーター名の欠落、文の誤配置、無効な try-with-resources 構文の修正方法を説明します。

このページの内容

Java コンパイラーは、変数名、メソッド名、クラス名などの名前が必要な位置でトークンに到達すると、<identifier> expected を報告します。javac が示した行と、そのカーソルの直前にある宣言または文を確認してください。パラメーターの型や名前の欠落、クラス本体内の実行文、無効なリソース宣言がよくある原因です。

<identifier> expected の診断を理解する

識別子は Java プログラムの要素に名前を付けます。Java の識別子には文字、数字、$、_ を含められますが、数字で始めたり予約語にしたりできません。パラメーター宣言には型と識別子の両方が必要です(例: int count)。クラス本体にはフィールドや初期化ブロックを置けますが、単独の代入やメソッド呼び出しは置けません。

javac は文法を続けられなくなった位置を示しますが、そこが根本原因とは限りません。示されたトークンを変更する前に、前の行の波括弧、セミコロン、コンマ、括弧を確認してください。最初の診断を直した後に再コンパイルします。後続のメッセージは同じ構文エラーの結果かもしれません。

パラメーターの型または名前の欠落を修正する

メソッドの各パラメーターには、データ型と変数名が必要です。次の宣言では型がありません。

public class Demo {
  static int square(x) {
    return x * x;
  }
}

この無効な形式を javac でコンパイルすると、次のような診断になります(行番号とカーソルは JDK により異なる場合があります)。

Demo.java:2: error: <identifier> expected
  static int square(x) {
                   ^
1 error

修正した宣言では x の前に int を追加します。

public class Demo {
  static int square(int x) {
    return x * x;
  }

  public static void main(String[] args) {
    System.out.println(square(10));
  }
}

javac Demo.java でコンパイルし、java Demo で実行すると、出力は次のようになります。

100

逆の誤りも失敗します。static int square(int) には型がありますが、パラメーター識別子がありません。名前を追加し、メソッド本体でも同じ名前を使います。class や return のような予約語ではなく、value のような有効な識別子を選んでください。

たとえば static int square(int) では javac がパラメーター名を期待するため、同じ診断が出ます。

Demo.java:2: error: <identifier> expected
  static int square(int) {
                       ^
1 error

実行文をメソッドまたは初期化ブロックへ移す

フィールドはクラスに直接宣言できますが、代入やメソッド呼び出しはメソッド、コンストラクター、または初期化ブロック内に置く必要があります。次のクラス本体は無効です。

public class Demo {
  private String name;
  name = "Naruto";
  System.out.println(name);
}

コンパイラーは、クラス本体の文法が宣言またはブロックを期待するトークン位置を報告します。

Demo.java:3: error: <identifier> expected
  name = "Naruto";
      ^
Demo.java:4: error: <identifier> expected
  System.out.println(name);
                    ^
3 errors

実行文をメソッドに移し、main から呼び出します。

public class Demo {
  private String name;

  void print() {
    name = "Naruto";
    System.out.println(name);
  }

  public static void main(String[] args) {
    Demo demo = new Demo();
    demo.print();
  }
}

成功時の出力は次のとおりです。

Naruto

代入をフィールドの初期化に使うなら、インスタンス初期化子({ name = "Naruto"; })も有効です。フィールド初期化子で private String name = "Naruto"; のような式も使えますが、初期化子やメソッドの外に単独のメソッド呼び出しは置けません。

try-with-resources でリソースを正しく宣言する

リソース指定部には BufferedReader reader = ... のような宣言、または初期化済みの final/実質 final 変数への参照を指定できます。既存の変数へ新しいリソースを代入する形式は宣言ではありません。

import java.io.BufferedReader;
import java.io.StringReader;

public class Demo {
  public static void main(String[] args) throws Exception {
    BufferedReader reader = null;
    try (reader = new BufferedReader(new StringReader("Java"))) {
      System.out.println(reader.readLine());
    }
  }
}

テストした JDK では、すでに宣言した reader への代入はリソース指定部で拒否されます。

Demo.java:7: error: the try-with-resources resource must either be a variable declaration or an expression denoting a reference to a final or effectively final variable
    try (reader = new BufferedReader(new StringReader("Java"))) {
                ^
1 error

代わりに try 内でリソースを宣言します。

import java.io.BufferedReader;
import java.io.StringReader;

public class Demo {
  public static void main(String[] args) throws Exception {
    try (BufferedReader reader = new BufferedReader(new StringReader("Java"))) {
      System.out.println(reader.readLine());
    }
  }
}

出力は次のとおりです。

Java

修正後の形式では、try ブロックの終了時に reader が自動的に閉じられます。後で必要な値はリソースが開いている間にコピーし、ブロック後に閉じたリソースを使わないでください。

再コンパイル前のチェックリスト

<identifier> expected が残る場合は、次の境界を順に確認します。

  1. すべてのパラメーターに型と名前があることを確認する。
  2. 名前が予約語でなく、数字で始まらず、意図した大文字小文字であることを確認する。
  3. 代入、メソッド呼び出しなどの実行文をメソッド、コンストラクター、初期化子へ移す。
  4. 前の行の波括弧と句読点を確認する。
  5. try-with-resources では宣言、または事前に初期化した実質 final リソースを使う。

これらは安定した Java 構文の規則で、Java SE 27 を含む現在の JDK に適用されます。コンパイラーのバージョンにより診断の文言や行番号は変わるため、メッセージとカーソルは周囲の文法への手掛かりとして扱い、元の誤りを必ず指すとは考えないでください。