Java break e continue

Um laço normalmente vai até o fim: roda todas as voltas, e cada volta roda o corpo inteiro. Às vezes você quer mudar isso no meio do caminho: parar tudo porque já achou o que procurava, ou pular só esta volta porque o item não interessa. Para isso existem o break e o continue.

Você vai aprender
  • break: sair do laço na hora, sem terminar as voltas.
  • continue: pular o resto desta volta e ir para a próxima.
  • Como os dois funcionam no for, no for-each e no while (e a armadilha do continue no while).
  • O laço while (true) com break.
  • Rótulos (externo:) para sair de dois laços de uma vez.
  • Os erros reais do javac com break e continue.

Os exemplos rodam no terminal da Ana (máquina fictícia notebook, pasta ~/java, JDK 25) com java Main.java. Esta aula usa os laços das aulas anteriores: while, for e for-each.


A ideia antes do código

A Ana está procurando as chaves de casa nas gavetas da cozinha. São dez gavetas.

  • Achou as chaves na terceira gaveta? Ela para de procurar. Não faz sentido abrir as outras sete. Isso é o break (em inglês, "quebrar", "interromper").
  • A quinta gaveta está emperrada? Ela pula essa e continua na sexta. Isso é o continue ("continuar", "seguir para a próxima").
breakcontinue
Tradução"interromper""continuar"
O que fazSai do laço inteiroAbandona só esta volta
Para onde o programa vaiPara a primeira linha depois do laçoPara o próximo teste da condição (no for, passa antes pelo passo)
Na gavetaAchei as chaves: paro de procurarGaveta emperrada: pulo para a próxima

break: sair do laço

Qual é o primeiro múltiplo de 7 a partir de 50? Vamos testar os números um por um e parar no primeiro que servir:

public class Main {
    public static void main(String[] args) {
        for (int i = 50; i <= 100; i++) {
            System.out.println("Testando " + i);
            if (i % 7 == 0) {
                System.out.println("Achei: " + i + " é múltiplo de 7");
                break;
            }
        }
        System.out.println("Fim do programa");
    }
}
$ java Main.java
Testando 50
Testando 51
Testando 52
Testando 53
Testando 54
Testando 55
Testando 56
Achei: 56 é múltiplo de 7
Fim do programa              « o break pulou direto para cá
LinhaO que faz
for (int i = 50; i <= 100; i++)Prepara 51 voltas, de 50 a 100.
if (i % 7 == 0)Resto zero na divisão por 7: é múltiplo.
break;Sai do for agora. As voltas de 57 a 100 nunca acontecem.
System.out.println("Fim do programa");A primeira linha depois do laço: é aqui que o break leva.

O laço estava preparado para 51 voltas e deu só 7. Em buscas com milhares de itens, parar no primeiro achado economiza muito trabalho.

break no for-each: procurar um nome

A Ana confere se uma convidada está na lista da festa. Ao achar, para; se o laço acabar sem achar, ela não está:

public class Main {
    public static void main(String[] args) {
        String[] convidados = {"Bruno", "Carla", "Ana", "Davi"};
        String procurado = "Ana";
        boolean achou = false;
        for (String nome : convidados) {
            System.out.println("Conferindo " + nome);
            if (nome.equals(procurado)) {
                achou = true;
                break;
            }
        }
        if (achou) {
            System.out.println(procurado + " está na lista!");
        } else {
            System.out.println(procurado + " não está na lista.");
        }
    }
}
$ java Main.java
Conferindo Bruno
Conferindo Carla
Conferindo Ana
Ana está na lista!            « o Davi nem foi conferido

A variável achou é uma bandeira (flag): começa false e vira true quando a busca dá certo. Depois do laço, ela conta o que aconteceu lá dentro. (Para comparar textos usamos equals, e não ==; veja Strings.)

while (true) + break

Às vezes a condição de parada só pode ser testada no meio do corpo. No caixa da loja, a Ana digita o valor de cada item e um 0 para fechar a conta. A pergunta "parar?" só faz sentido depois de ler o valor. O jeito clássico é um laço "infinito" que tem uma saída lá dentro (o Scanner, que lê o teclado, tem a sua aula: Scanner):

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner teclado = new Scanner(System.in);
        int soma = 0;
        while (true) {
            System.out.print("Valor do item (0 para fechar a conta): ");
            int valor = teclado.nextInt();
            if (valor == 0) {
                break;
            }
            soma += valor;
        }
        System.out.println("Total: R$ " + soma);
    }
}
$ java Main.java
Valor do item (0 para fechar a conta): 25
Valor do item (0 para fechar a conta): 10
Valor do item (0 para fechar a conta): 7
Valor do item (0 para fechar a conta): 0
Total: R$ 42

O while (true) sozinho nunca terminaria (veja o laço infinito em while); é o break que dá a saída. Repare que o 0 não é somado: o break acontece antes da linha soma += valor. Esse padrão, "ler, testar, sair ou processar", é muito comum em menus e leitura de dados.


continue: pular uma volta

O continue não sai do laço: ele abandona o resto da volta atual e passa para a próxima. Mostrando só os pares de 1 a 10:

public class Main {
    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) {
            if (i % 2 != 0) {
                continue;
            }
            System.out.println(i + " é par");
        }
    }
}
$ java Main.java
2 é par
4 é par
6 é par
8 é par
10 é par

Quando i é ímpar (resto diferente de zero), o continue pula o println. No for, o "ir para a próxima volta" passa pelo passo (i++) e depois pela condição, então a contagem segue normalmente.

Um uso real: pular dados que não contam

Na planilha da professora, -1 quer dizer "o aluno faltou à prova". Essas notas não podem entrar na média:

public class Main {
    public static void main(String[] args) {
        int[] notas = {8, -1, 7, 9, -1, 6};
        int soma = 0;
        int validas = 0;
        for (int nota : notas) {
            if (nota == -1) {
                System.out.println("Aluno faltou, pulando...");
                continue;
            }
            soma += nota;
            validas++;
        }
        System.out.println("Média das provas feitas: " + (double) soma / validas);
    }
}
$ java Main.java
Aluno faltou, pulando...
Aluno faltou, pulando...
Média das provas feitas: 7.5  « (8 + 7 + 9 + 6) / 4

O (double) transforma a soma em número com vírgula antes da divisão, para não perder o ",5" (veja Conversão de Tipos).

continue ou if?

Todo continue pode ser trocado por um if que envolve o resto do corpo: if (nota != -1) { soma += nota; validas++; }. O continue ganha quando as condições de "pular" são várias e ficam no topo do laço, como uma lista de "isto não me interessa". Com uma condição só, os dois são igualmente bons.

Missão: no extrato da Ana, valores negativos são saques e positivos são depósitos. Use continue para pular os saques e somar só os depósitos. O resultado deve ser Total depositado: 390.

public class Main {
    public static void main(String[] args) {
        int[] extrato = {100, -30, 250, -80, 40};
        int depositos = 0;
        for (int valor : extrato) {
            // pule os valores negativos aqui

            depositos += valor;
        }
        System.out.println("Total depositado: " + depositos);
    }
}
public class Main {
    public static void main(String[] args) {
        int[] extrato = {100, -30, 250, -80, 40};
        int depositos = 0;
        for (int valor : extrato) {
            if (valor < 0) {
                continue;
            }
            depositos += valor;
        }
        System.out.println("Total depositado: " + depositos);
    }
}

A armadilha do continue no while

No for, o passo fica no cabeçalho e roda mesmo depois de um continue. No while, o passo é uma linha comum do corpo, e o continue pode pulá-la. Veja o mesmo "mostrar os pares", agora com while:

public class Main {
    public static void main(String[] args) {
        int i = 0;
        while (i < 10) {
            if (i % 2 != 0) {
                continue;
            }
            System.out.println(i + " é par");
            i++;
        }
    }
}
$ java Main.java
0 é par
^C                           « travou; a Ana apertou Ctrl+C depois de 4 segundos
$ echo $?
130

O que aconteceu, volta por volta: com i = 0, mostrou "0 é par" e fez i++. Com i = 1, o continue mandou de volta para a condição sem passar pelo i++. O i ficou 1 para sempre: laço infinito, e silencioso.

A correção é fazer o passo antes de qualquer continue:

public class Main {
    public static void main(String[] args) {
        int i = 0;
        while (i < 10) {
            i++;
            if (i % 2 != 0) {
                continue;
            }
            System.out.println(i + " é par");
        }
    }
}
$ java Main.java
2 é par
4 é par
6 é par
8 é par
10 é par

Repare que agora o i++ vem primeiro, então o laço testa os valores de 1 a 10 (e não de 0 a 9). Por isso o 10 aparece e o 0 não. Sempre que usar continue num while, pergunte-se: "o passo ainda roda?".


Laços aninhados: break só sai de um

Quando há um laço dentro de outro (assunto da próxima aula, Laços Aninhados), o break e o continue agem só no laço mais de dentro, aquele onde eles estão escritos.

Vamos procurar dois números de 1 a 9 cuja multiplicação dá 24. O laço de fora escolhe o i; o de dentro testa cada j:

public class Main {
    public static void main(String[] args) {
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= 9; j++) {
                if (i * j == 24) {
                    System.out.println("Achei: " + i + " x " + j + " = 24");
                    break;
                }
            }
        }
        System.out.println("Fim da busca");
    }
}
$ java Main.java
Achei: 3 x 8 = 24
Achei: 4 x 6 = 24            « o laço de fora continuou!
Achei: 6 x 4 = 24
Achei: 8 x 3 = 24
Fim da busca

A Ana queria só o primeiro par, mas vieram quatro. O break saiu do laço do j, só que o laço do i seguiu para o próximo número e a busca recomeçou. Para sair dos dois laços de uma vez, o Java tem os rótulos.

Rótulos: break externo

Um rótulo (label) é um nome que você dá a um laço, escrito antes dele e seguido de dois-pontos. Depois, break nome; sai do laço com esse nome, mesmo de dentro de outro laço:

public class Main {
    public static void main(String[] args) {
        externo:
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= 9; j++) {
                if (i * j == 24) {
                    System.out.println("Achei: " + i + " x " + j + " = 24");
                    break externo;
                }
            }
        }
        System.out.println("Fim da busca");
    }
}
$ java Main.java
Achei: 3 x 8 = 24
Fim da busca                 « saiu dos dois laços de uma vez
externo:
O rótulo: um nome à sua escolha (as regras são as dos nomes de variáveis) mais dois-pontos, logo antes do laço que ele nomeia. externo, fora, busca são nomes comuns.
for (…)
O laço de fora, que agora se chama externo.
break externo;
"Saia do laço chamado externo". O programa vai para a primeira linha depois dele.

continue externo

O continue também aceita rótulo: ele abandona o laço de dentro e vai para a próxima volta do laço de fora. Na agenda do consultório, quando chega a hora do almoço (10h, num dia de expediente curto), o dia acaba e passa-se para o próximo:

public class Main {
    public static void main(String[] args) {
        externo:
        for (int dia = 1; dia <= 3; dia++) {
            for (int hora = 8; hora <= 11; hora++) {
                if (hora == 10) {
                    System.out.println("Dia " + dia + ": almoço cedo, encerrando o dia");
                    continue externo;
                }
                System.out.println("Dia " + dia + ", " + hora + "h: atendendo");
            }
            System.out.println("Esta linha nunca aparece");
        }
    }
}
$ java Main.java
Dia 1, 8h: atendendo
Dia 1, 9h: atendendo
Dia 1: almoço cedo, encerrando o dia
Dia 2, 8h: atendendo
Dia 2, 9h: atendendo
Dia 2: almoço cedo, encerrando o dia
Dia 3, 8h: atendendo
Dia 3, 9h: atendendo
Dia 3: almoço cedo, encerrando o dia

O continue externo pulou as 10h e 11h e a linha "Esta linha nunca aparece", que fica no corpo do laço de fora, e foi direto para o próximo dia.

Use rótulos com moderação

Rótulos resolvem bem o "sair de dois laços", mas código cheio deles fica difícil de seguir. Quando o laço duplo ficar grande, a alternativa mais limpa é colocá-lo num método e usar return, que sai do método inteiro (e, portanto, de todos os laços), assunto de Valores de Retorno.


Formas diferentes de parar um laço

Para "parar no primeiro múltiplo de 7", o break não é a única saída. Dá para colocar a parada na própria condição:

public class Main {
    public static void main(String[] args) {
        int encontrado = -1;
        for (int i = 50; i <= 100 && encontrado == -1; i++) {
            if (i % 7 == 0) {
                encontrado = i;
            }
        }
        System.out.println("Primeiro múltiplo de 7: " + encontrado);
    }
}
$ java Main.java
Primeiro múltiplo de 7: 56

Aqui o laço continua enquanto não passou de 100 e (&&) ainda não achou nada. O -1 é um valor "impossível" que significa "nada encontrado ainda".

FormaComo ficaQuando usar
breakSai assim que acharBuscas: é o mais direto e o mais comum.
Condição com bandeirai <= 100 && encontrado == -1Quando você quer ler a regra de parada no cabeçalho.
while (true) + breakSai de dentro do corpoQuando o teste só pode ser feito no meio (depois de ler um dado).
break rótuloSai de vários laçosBusca em laços aninhados.
returnSai do método todoQuando o laço está num método que já tem a resposta (Nível 2).
E o break do switch?

Você já viu break em switch, onde ele encerra um case. É a mesma palavra com a mesma ideia ("saia daqui"). Cuidado com um switch dentro de um laço: um break dentro do switch sai só do switch, não do laço. Os switch com setas (switch com Setas) não precisam de break.


Quando dá errado

"break outside switch or loop"
public class Main {
    public static void main(String[] args) {
        int idade = 15;
        if (idade < 18) {
            System.out.println("Menor de idade");
            break;
        }
    }
}
$ java Main.java
Main.java:6: error: break outside switch or loop
            break;
            ^
1 error
error: compilation failed

O que quer dizer: "break fora de switch ou laço". O break só existe dentro de um laço ou de um switch; um if sozinho não é um laço. Quem escreve isso geralmente quer "parar o programa" ou "sair do if".

Como consertar: para não rodar o resto, use else (veja if, else). Para encerrar o método, return;.

"continue outside of loop"
public class Main {
    public static void main(String[] args) {
        int idade = 15;
        if (idade < 18) {
            continue;
        }
    }
}
$ java Main.java
Main.java:5: error: continue outside of loop
            continue;
            ^
1 error
error: compilation failed

O que quer dizer: "continue fora de laço". O continue só existe dentro de laços (nem no switch ele vale sozinho).

"undefined label"
public class Main {
    public static void main(String[] args) {
        externo:
        for (int i = 1; i <= 3; i++) {
            for (int j = 1; j <= 3; j++) {
                if (j == 2) {
                    break exterior;
                }
            }
        }
    }
}
$ java Main.java
Main.java:7: error: undefined label: exterior
                    break exterior;
                    ^
1 error
error: compilation failed

O que quer dizer: "rótulo não definido: exterior". O laço se chama externo, e o break pediu exterior. O rótulo precisa ser escrito igualzinho, e o break tem que estar dentro do laço rotulado.

"unreachable statement" depois do break
public class Main {
    public static void main(String[] args) {
        for (int i = 1; i <= 5; i++) {
            break;
            System.out.println(i);
        }
    }
}
$ java Main.java
Main.java:5: error: unreachable statement
            System.out.println(i);
            ^
1 error
error: compilation failed

O que quer dizer: "instrução inalcançável". Um break (ou continue) solto, sem if, faz o programa sair sempre, então nada depois dele pode rodar. O javac entende que é um engano. Quase sempre faltou o if em volta do break.

O laço trava depois de usar continue

Se é um while ou do-while, o continue provavelmente está pulando o passo (i++). Veja a armadilha do continue no while acima: mova o passo para antes do continue, ou troque o laço por um for.


Referência

FormaO que faz
break;Sai do laço (ou switch) mais de dentro
continue;Vai para a próxima volta do laço mais de dentro (no for, passa pelo passo)
nome: antes de um laçoDá um rótulo ao laço
break nome;Sai do laço rotulado nome, mesmo de dentro de outro laço
continue nome;Vai para a próxima volta do laço rotulado nome
while (true) { … if (…) break; … }Laço com a saída no meio do corpo

Exercícios

1. Parar na hora certa

Complete para o laço parar quando encontrar o nome "Carla":

for (String nome : nomes) { if (nome.equals("Carla")) { } }

2. Pular uma volta

Complete para não mostrar o número 5 (e mostrar todos os outros de 1 a 10):

for (int i = 1; i <= 10; i++) { if (i == 5) { } System.out.println(i); }

3. Sair dos dois laços

O laço de fora tem o rótulo busca:. Complete para sair dos dois:

if (achou) { }

4. O que for (int i = 1; i <= 5; i++) { if (i == 3) break; System.out.print(i); } mostra?

5. E com continue no lugar do break?

6. Um break (sem rótulo) dentro de um laço que está dentro de outro laço…

7. Por que um continue pode travar um while e não um for?

Missão final: este programa mostra todos os pares de 1 a 9 que multiplicados dão 36. Mude-o para mostrar só o primeiro (Achei: 4 x 9 = 36) e parar, usando um rótulo e break com o nome dele.

public class Main {
    public static void main(String[] args) {
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= 9; j++) {
                if (i * j == 36) {
                    System.out.println("Achei: " + i + " x " + j + " = 36");
                }
            }
        }
    }
}
public class Main {
    public static void main(String[] args) {
        externo:
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= 9; j++) {
                if (i * j == 36) {
                    System.out.println("Achei: " + i + " x " + j + " = 36");
                    break externo;
                }
            }
        }
    }
}

Resumo

  • break sai do laço na hora; o programa segue na primeira linha depois dele.
  • continue pula o resto da volta atual e vai para a próxima (no for, passando pelo passo).
  • Os dois funcionam em for, for-each, while e do-while. O break também funciona no switch.
  • No while, cuidado: um continue antes do passo cria um laço infinito.
  • while (true) + break é o padrão para "ler, testar, sair ou processar".
  • Sem rótulo, eles agem só no laço mais de dentro. Com rótulo (externo: + break externo;), saem ou pulam no laço de fora.
  • Fora de um laço, dão erro de compilação: break outside switch or loop e continue outside of loop.