HOWTO · Java

Cómo corregir el error `<identifier> expected` en Java

Aprende qué significa `<identifier> expected` para javac y cómo corregir parámetros sin nombre, sentencias mal ubicadas y una sintaxis inválida de try-with-resources.

En esta página

El compilador de Java informa <identifier> expected cuando llega a un token donde la sintaxis requiere un nombre, como el de una variable, método o clase. Revisa la línea marcada por javac y después la declaración o sentencia inmediatamente anterior al cursor. A menudo falta el tipo o nombre de un parámetro, hay una sentencia ejecutable en el cuerpo de la clase o se declaró mal un recurso.

Comprender el diagnóstico <identifier> expected

Un identificador nombra un elemento de un programa Java. Puede contener letras, dígitos, $ y _, pero no comenzar con un dígito ni ser una palabra reservada. Una declaración de parámetro necesita un tipo y un identificador, por ejemplo int count. El cuerpo de una clase puede contener campos y bloques de inicialización, pero no una asignación o llamada de método independiente.

javac señala el lugar donde ya no puede continuar la gramática; ese lugar no siempre es la causa original. Comprueba las llaves, punto y coma, comas y paréntesis anteriores antes de cambiar el token marcado. Compila de nuevo después de corregir el primer diagnóstico, porque los mensajes posteriores pueden derivarse del mismo error.

Corregir la falta del tipo o nombre de un parámetro

Cada parámetro de método necesita un tipo de datos seguido de un nombre de variable. Esta declaración omite el tipo:

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

Al compilar esta forma inválida con javac aparece un diagnóstico como el siguiente (el número de línea y el cursor pueden variar según el JDK):

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

La declaración corregida proporciona int antes de x:

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

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

Compílala con javac Demo.java y ejecútala con java Demo; la salida es:

100

El error inverso también falla: static int square(int) tiene tipo, pero no identificador de parámetro. Añade un nombre y usa el mismo nombre en el cuerpo del método. No uses una palabra clave como class o return; elige un identificador válido como value.

Por ejemplo, static int square(int) produce el mismo diagnóstico porque javac espera un nombre de parámetro:

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

Mover las sentencias ejecutables a un método o inicializador

Los campos se pueden declarar directamente en una clase, pero las asignaciones y llamadas de método deben estar dentro de un método, constructor o bloque inicializador. Este código del cuerpo de la clase es inválido:

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

El compilador informa los tokens donde la gramática del cuerpo de la clase espera una declaración o un bloque:

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

Coloca las sentencias ejecutables en un método y llámalo desde 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();
  }
}

La salida correcta es:

Naruto

Si la asignación debe inicializar un campo, también sirve un inicializador de instancia ({ name = "Naruto"; }). Un inicializador de campo puede usar una expresión como private String name = "Naruto";, pero no una llamada de método independiente fuera de un inicializador o método.

Declarar correctamente los recursos en try-with-resources

La especificación de recursos acepta una declaración como BufferedReader reader = ... o una referencia a una variable final o efectivamente final ya inicializada. Asignar un recurso nuevo a una variable dentro de la especificación no es una declaración válida:

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

En el JDK probado, la asignación a reader ya declarado se rechaza en la especificación de recursos:

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

Declara el recurso dentro de 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());
    }
  }
}

Imprime:

Java

La forma corregida cierra reader automáticamente al final del bloque try. Si necesitas el lector después, copia el valor necesario mientras el recurso esté abierto; no uses el recurso cerrado después del bloque.

Lista de comprobación antes de recompilar

Si <identifier> expected continúa, revisa estos límites en orden:

  1. Confirma que cada parámetro tenga tipo y nombre.
  2. Comprueba que el nombre no sea una palabra clave, no empiece por un dígito y use las mayúsculas previstas.
  3. Mueve las asignaciones, llamadas de método y demás sentencias ejecutables a un método, constructor o inicializador.
  4. Revisa las llaves y la puntuación de las líneas anteriores.
  5. En try-with-resources, usa una declaración o un recurso efectivamente final inicializado previamente.

Estas reglas forman parte de la sintaxis estable de Java y se aplican a las versiones actuales del JDK, incluido Java SE 27. La versión del compilador puede cambiar el texto exacto o el número de línea del diagnóstico; considera el mensaje y el cursor una pista sobre la gramática cercana, no una garantía de que el cursor marque el error original.