HOWTO · Java

Den Fehler `<identifier> expected` in Java beheben

Erfahren Sie, was javac mit `<identifier> expected` bedeutet und wie Sie fehlende Parameternamen, falsch platzierte Anweisungen und eine ungültige try-with-resources-Syntax beheben.

Auf dieser Seite

Der Java-Compiler meldet <identifier> expected, wenn die Syntax an dieser Stelle einen Namen wie einen Variablen-, Methoden- oder Klassennamen verlangt. Prüfen Sie die von javac markierte Zeile und die Deklaration oder Anweisung direkt davor. Häufig fehlen ein Parametertyp oder -name, eine ausführbare Anweisung steht im Klassenrumpf oder eine Ressource ist ungültig deklariert.

Die Diagnose <identifier> expected verstehen

Ein Bezeichner benennt ein Java-Element. Er darf Buchstaben, Ziffern, $ und _ enthalten, aber nicht mit einer Ziffer beginnen oder ein reserviertes Schlüsselwort sein. Eine Parameterdeklaration benötigt Typ und Bezeichner, etwa int count. Ein Klassenrumpf darf Felder und Initialisierungsblöcke enthalten, aber keine freie Zuweisung oder keinen Methodenaufruf.

javac meldet die Stelle, an der die Grammatik nicht fortgesetzt werden kann; das ist nicht immer die eigentliche Ursache. Prüfen Sie fehlende Klammern, Semikolons und Kommas vor dem markierten Token. Kompilieren Sie nach der ersten Korrektur erneut, weil spätere Meldungen dieselbe Ursache haben können.

Einen fehlenden Parametertyp oder -namen beheben

Jeder Methodenparameter benötigt einen Datentyp gefolgt von einem Variablennamen. Diese ungültige Deklaration lässt den Typ weg:

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

Beim Kompilieren mit javac erscheint beispielsweise folgende Diagnose (Zeilennummer und Caret können je nach JDK abweichen):

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

Die korrigierte Deklaration ergänzt int vor x:

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

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

Kompilieren Sie mit javac Demo.java und starten Sie mit java Demo; die Ausgabe lautet:

100

Auch der umgekehrte Fehler schlägt fehl: static int square(int) hat einen Typ, aber keinen Parameterbezeichner. Ergänzen Sie einen Namen und verwenden Sie ihn im Methodenrumpf. Verwenden Sie kein Schlüsselwort wie class oder return, sondern einen gültigen Bezeichner wie value.

Beispielsweise meldet static int square(int) dieselbe Diagnose, weil javac einen Parameternamen erwartet:

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

Ausführbare Anweisungen in eine Methode oder Initialisierung verschieben

Felder können direkt in einer Klasse deklariert werden; Zuweisungen und Methodenaufrufe müssen jedoch in einer Methode, einem Konstruktor oder Initialisierungsblock stehen. Dieser Klassenrumpf ist ungültig:

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

Der Compiler meldet die Tokens, an denen der Klassenrumpf eine Deklaration oder einen Block erwartet:

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

Verschieben Sie die ausführbaren Anweisungen in eine Methode und rufen Sie sie aus main auf:

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();
  }
}

Die erfolgreiche Ausgabe lautet:

Naruto

Soll die Zuweisung ein Feld initialisieren, ist auch ein Instanzinitialisierer ({ name = "Naruto"; }) gültig. Ein Feldinitialisierer darf einen Ausdruck wie private String name = "Naruto"; verwenden, aber keinen alleinstehenden Methodenaufruf außerhalb einer Initialisierung oder Methode.

Ressourcen in try-with-resources richtig deklarieren

Die Ressourcenspezifikation akzeptiert eine Deklaration wie BufferedReader reader = ... oder eine Referenz auf eine bereits initialisierte finale beziehungsweise effektiv finale Variable. Eine neue Ressource einer Variablen zuzuweisen, ist dort keine Deklaration:

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());
    }
  }
}

Im getesteten JDK wird diese Zuweisung in der Ressourcenspezifikation abgelehnt:

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

Deklarieren Sie die Ressource stattdessen innerhalb von 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());
    }
  }
}

Das Programm gibt Folgendes aus:

Java

Die korrigierte Form schließt reader am Ende des try-Blocks automatisch. Wenn der Code den Reader danach benötigt, kopieren Sie den Wert bei geöffneter Ressource und verwenden Sie die geschlossene Ressource nicht nach dem Block.

Checkliste vor dem erneuten Kompilieren

Wenn <identifier> expected bestehen bleibt, prüfen Sie diese Grenzen in dieser Reihenfolge:

  1. Bestätigen Sie, dass jeder Parameter Typ und Namen besitzt.
  2. Prüfen Sie, dass der Name kein Schlüsselwort ist, nicht mit einer Ziffer beginnt und die gewünschte Groß-/Kleinschreibung verwendet.
  3. Verschieben Sie Zuweisungen, Methodenaufrufe und andere ausführbare Anweisungen in Methode, Konstruktor oder Initialisierer.
  4. Prüfen Sie geschweifte Klammern und Satzzeichen in den vorherigen Zeilen.
  5. Verwenden Sie für try-with-resources eine Deklaration oder eine zuvor initialisierte effektiv finale Ressource.

Diese Regeln gehören zur stabilen Java-Syntax und gelten für aktuelle JDK-Versionen einschließlich Java SE 27. Die Compilerversion kann Wortlaut oder Zeilennummer ändern. Betrachten Sie Meldung und Caret daher als Hinweis auf die umgebende Grammatik, nicht als Garantie, dass das Caret den ursprünglichen Tippfehler markiert.