W3docs

Instruções Rotuladas em Java

Use rótulos em Java para interromper ou continuar laços externos a partir de laços aninhados.

Um break simples sai do laço mais interno e um continue simples pula uma iteração dele. Quando você está dentro de laços aninhados e precisa controlar o laço externo a partir do interno, Java oferece as instruções rotuladas: um nome que você pode associar a um laço, e um break ou continue que o referencia por esse nome.

Este capítulo aborda como definir um rótulo, como o break e o continue rotulados alteram o fluxo, quando (raramente) usá-los e as alternativas mais limpas a considerar primeiro.

Esta é a coisa mais próxima que Java tem de goto — e é intencionalmente limitada a laços (e switch).

Definindo um rótulo

Um rótulo é um identificador seguido de dois-pontos, colocado imediatamente antes de um laço:

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

O nome (outer aqui) segue as mesmas regras de qualquer identificador Java. Não há obrigação de chamá-lo de outersearchLoop, rows ou qualquer nome válido funciona. Escolha um nome que diga por que o rótulo está ali.

break rotulado

break <label>; sai do laço marcado com aquele rótulo, independentemente de quão profundamente aninhado você esteja dentro dele:

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

Sem o break rotulado, você precisaria de uma variável de controle ou teria que reestruturar o código. Com ele, você sai de ambos os laços ao mesmo tempo no instante em que o alvo é encontrado.

continue rotulado

continue <label>; pula o restante da iteração interna atual e continua com a próxima iteração do laço externo rotulado:

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

Quando o laço interno encontra um valor negativo, o restante daquela linha é ignorado e passamos para a próxima linha.

Use com moderação

Os rótulos funcionam, mas são fáceis de abusar. Sempre que você sentir vontade de usar um, considere as alternativas primeiro:

  • Extraia um método auxiliar. Dentro de um método, um return simples sai de todos os laços de uma vez e costuma ser mais 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;
    }
  • Use uma variável de controle — um pouco menos elegante, mas explícita e sem 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; }
      }
    }
  • Use streams para problemas de filtragem em vez de laços aninhados.

Recorra a rótulos quando as alternativas realmente prejudicam a legibilidade — tipicamente em dois ou três níveis de profundidade com uma intenção clara de "abortar a busca" ou "próxima iteração externa".

Rótulos e switch

Rótulos também funcionam com switch, embora seja raro:

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

Na prática, isso nunca adiciona clareza em relação a um break simples.

Um exemplo completo

java— editable, runs on the server

O que vem a seguir

Você concluiu os capítulos de fluxo de controle: condicionais, o operador ternário, switches, laços e as instruções que os interrompem. O próximo tópico é a parte sobre métodos — agrupando blocos de código para que você possa chamá-los pelo nome.

Prática

Prática
O que um break rotulado faz?
O que um break rotulado faz?
Was this page helpful?