W3docs

Sentencias etiquetadas en Java

Usa etiquetas en Java para hacer break o continue en bucles externos desde dentro de bucles anidados.

Un break simple sale del bucle más interno y un continue simple omite una iteración del mismo. Cuando estás dentro de bucles anidados y necesitas controlar el bucle externo desde el interno, Java te ofrece las sentencias etiquetadas: un nombre que puedes asociar a un bucle, y un break o continue que lo apunta por ese nombre.

Este capítulo cubre cómo definir una etiqueta, cómo el break y continue etiquetados cambian el flujo, cuándo usarlos (raramente) y las alternativas más claras que deberías considerar primero.

Esto es lo más parecido que tiene Java a goto — y está intencionalmente limitado a bucles (y switch).

Definir una etiqueta

Una etiqueta es un identificador seguido de dos puntos, colocado inmediatamente antes de un bucle:

outer:
for (int i = 0; i < 5; i++) {
  // ...
}

El nombre (outer aquí) sigue las mismas reglas que cualquier identificador Java. No es obligatorio llamarlo outer — searchLoop, rows, cualquier nombre válido funciona. Elige un nombre que indique por qué está la etiqueta.

break etiquetado

break <label>; sale del bucle marcado con esa etiqueta, sin importar cuán profundamente anidado estés dentro de él:

int[][] grid = {
  {1, 2, 3},
  {4, 5, 6},
  {7, 8, 9}
};
int target = 5;
int foundRow = -1, foundCol = -1;

search:
for (int r = 0; r < grid.length; r++) {
  for (int c = 0; c < grid[r].length; c++) {
    if (grid[r][c] == target) {
      foundRow = r;
      foundCol = c;
      break search;
    }
  }
}
System.out.println("found at " + foundRow + "," + foundCol);

Sin el break etiquetado, necesitarías una variable bandera o reestructurar el código. Con él, sales de ambos bucles a la vez en el momento en que se encuentra el objetivo.

continue etiquetado

continue <label>; omite el resto de ambas la iteración interna actual y continúa con la siguiente iteración del bucle externo etiquetado:

rowLoop:
for (int r = 0; r < grid.length; r++) {
  for (int c = 0; c < grid[r].length; c++) {
    if (grid[r][c] < 0) {
      continue rowLoop;     // skip the rest of this row
    }
    process(grid[r][c]);
  }
}

Cuando el bucle interno encuentra un valor negativo, se omite el resto de esa fila y se continúa con la siguiente.

Úsalos con moderación

Las etiquetas funcionan, pero es fácil abusar de ellas. Siempre que vayas a usar una, considera primero las alternativas:

  • Extrae un método auxiliar. Dentro de un método, un return simple sale de todos los bucles a la vez y suele ser más claro:

    static int[] find(int[][] grid, int target) {
      for (int r = 0; r < grid.length; r++) {
        for (int c = 0; c < grid[r].length; c++) {
          if (grid[r][c] == target) return new int[]{r, c};
        }
      }
      return null;
    }
  • Usa una bandera — un poco menos limpio pero explícito y sin goto:

    boolean found = false;
    for (int r = 0; !found && r < grid.length; r++) {
      for (int c = 0; c < grid[r].length; c++) {
        if (grid[r][c] == target) { found = true; break; }
      }
    }
  • Usa streams para problemas de filtrado en lugar de bucles anidados.

Recurre a las etiquetas cuando las alternativas realmente perjudican la legibilidad — típicamente con dos o tres niveles de profundidad y con una intención clara de "abortar la búsqueda" o "siguiente iteración externa".

Etiquetas y switch

Las etiquetas también funcionan con switch, aunque es poco frecuente:

sw:
switch (cmd) {
  case "x":
    if (someCondition) break sw;
    // ...
    break;
}

En la práctica, esto nunca aporta más claridad que un break simple.

Un ejemplo práctico

java— editable, runs on the server

Qué sigue

Has terminado los capítulos de flujo de control: condicionales, el operador ternario, switch, bucles y las sentencias que los interrumpen. A continuación viene la parte sobre métodos — cómo empaquetar bloques de código para poder invocarlos por nombre.

Práctica

Práctica
¿Qué hace un break etiquetado?
¿Qué hace un break etiquetado?
Was this page helpful?