Java for
Na aula de while, todo contador tinha três peças espalhadas pelo código: o início antes do laço, a condição no while e o passo lá no fim do corpo. O for junta as três numa linha só. É o laço mais usado do Java quando você sabe quantas vezes quer repetir.
- A anatomia do
for: início; condição; passo, e em que ordem cada parte roda. - Contar para cima, para baixo, de 2 em 2 ou de qualquer tamanho de passo.
- Os dois padrões clássicos: acumular (somar de 1 a 100) e repetir com fórmula (a tabuada).
- Onde a variável do laço "existe" (o escopo) e o erro
cannot find symbolquando você a usa fora dele. - Quando usar
fore quando usarwhile.
Os exemplos rodam no terminal da Ana (máquina fictícia notebook, pasta ~/java, JDK 25) com java Main.java.
A ideia antes do código
Pense numa academia. O treino da Ana diz: "faça 10 flexões". Para cumprir, ela faz três coisas sem nem perceber:
- Começa a contar do 1.
- Antes de cada flexão, verifica se ainda não passou de 10.
- Depois de cada flexão, conta mais uma.
É exatamente o contador do while. O for (em inglês, "para": "para i de 1 até 10…") escreve essas três coisas juntas, no topo do laço, onde é fácil ver de relance quantas voltas serão.
Compare o mesmo laço nos dois jeitos:
Com while | Com for |
|---|---|
int i = 1;
while (i <= 5) {
System.out.println("Volta " + i);
i++;
} |
for (int i = 1; i <= 5; i++) {
System.out.println("Volta " + i);
} |
Os dois fazem a mesma coisa. No for, o corpo fica só com o que importa (a tarefa) e o "controle" do laço fica todo no cabeçalho.
O primeiro for
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
System.out.println("Volta " + i);
}
System.out.println("Fim!");
}
}
$ java Main.java Volta 1 Volta 2 Volta 3 Volta 4 Volta 5 Fim!
Anatomia do for
- for
- A palavra-chave: "para".
- (int i = 1;
- O início: cria a variável do laço e dá o valor inicial. Roda uma vez só, antes de tudo.
- i <= 5;
- A condição: testada antes de cada volta. Se der
true, roda o corpo; se derfalse, o laço acaba. - i++)
- O passo: roda depois de cada volta, antes do próximo teste. Repare: depois dele não vai
;. - { … }
- O corpo: o que se repete.
i?
É uma tradição antiga da matemática e da programação: i de "índice". Laços dentro de laços costumam usar j e k. Você pode usar qualquer nome (volta, flexao, mes); quando o nome ajudar a entender, prefira-o.
A ordem exata das partes
Os três pedaços do cabeçalho não rodam da esquerda para a direita a cada volta. A ordem é esta:
- Início (
int i = 1): uma vez só. - Condição (
i <= 5): se forfalse, pula para depois da}e acabou. - Corpo: mostra "Volta i".
- Passo (
i++): soma 1. - Volta ao passo 2.
| Momento | i | Condição i <= 5 | Acontece |
|---|---|---|---|
| Início | 1 | true | Volta 1, depois i++ |
| 2º teste | 2 | true | Volta 2, depois i++ |
| 3º teste | 3 | true | Volta 3, depois i++ |
| 4º teste | 4 | true | Volta 4, depois i++ |
| 5º teste | 5 | true | Volta 5, depois i++ |
| 6º teste | 6 | false | Sai do laço e mostra "Fim!" |
Quantas voltas? A fórmula rápida
Com passo 1, o número de voltas é fácil de calcular:
for (int i = 1; i <= N; i++)→ N voltas (de 1 a N).for (int i = 0; i < N; i++)→ N voltas (de 0 a N-1).
A segunda forma, começando do 0 e usando <, parece estranha agora, mas é a mais comum de todas no Java. O motivo aparece na aula de Arrays: as posições de um array começam no 0.
Contando de outros jeitos
Para baixo
Comece alto, teste com >= e use i-- (diminui 1):
public class Main {
public static void main(String[] args) {
for (int i = 5; i >= 1; i--) {
System.out.println(i + "...");
}
System.out.println("Fogo!");
}
}
$ java Main.java 5... 4... 3... 2... 1... Fogo!
De 2 em 2 (ou de qualquer tamanho)
O passo pode ser qualquer conta que muda a variável. i += 2 soma 2 de cada vez (veja Operadores de Atribuição). Neste exemplo usamos print (sem "ln"), que não pula linha, para os números ficarem lado a lado; o println() vazio no fim pula a linha (veja print e println):
public class Main {
public static void main(String[] args) {
for (int i = 0; i <= 10; i += 2) {
System.out.print(i + " ");
}
System.out.println();
for (int i = 1; i <= 10; i += 2) {
System.out.print(i + " ");
}
System.out.println();
for (int i = 0; i <= 100; i += 25) {
System.out.print(i + " ");
}
System.out.println();
}
}
$ java Main.java 0 2 4 6 8 10 « pares: começa em 0, passo 2 1 3 5 7 9 « ímpares: começa em 1, passo 2 0 25 50 75 100 « passo 25
Repare que o início decide se saem pares ou ímpares, e o passo decide o tamanho do pulo. Também dá para pular com outras contas: i *= 2 (dobra a cada volta), i -= 3 (desce de 3 em 3).
Com letras
Um char é, por dentro, um número (veja char e boolean), então ele também pode ser a variável do laço:
public class Main {
public static void main(String[] args) {
for (char letra = 'a'; letra <= 'e'; letra++) {
System.out.print(letra + " ");
}
System.out.println();
}
}
$ java Main.java a b c d e
Filtrando dentro do laço
O corpo do for pode ter qualquer coisa, inclusive um if. Para mostrar os múltiplos de 3 até 30, percorra todos e mostre só os que têm resto zero na divisão por 3 (o % é o resto, veja Operadores Aritméticos):
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 30; i++) {
if (i % 3 == 0) {
System.out.print(i + " ");
}
}
System.out.println();
}
}
$ java Main.java 3 6 9 12 15 18 21 24 27 30
O mesmo resultado sai de for (int i = 3; i <= 30; i += 3), sem if e com um terço das voltas. Muitas vezes há mais de um jeito; o mais simples costuma ser o melhor.
Padrão 1: acumular (somar de 1 a 100)
Conta-se que o matemático Gauss, criança, recebeu do professor a tarefa de somar todos os números de 1 a 100. Para o computador, é um laço de três linhas. O truque é ter uma variável acumuladora, criada antes do laço com zero, que vai recebendo cada número:
public class Main {
public static void main(String[] args) {
int soma = 0;
for (int i = 1; i <= 100; i++) {
soma += i;
}
System.out.println("1 + 2 + ... + 100 = " + soma);
}
}
$ java Main.java 1 + 2 + ... + 100 = 5050
| Linha | O que faz |
|---|---|
int soma = 0; | O acumulador. Fica fora do laço: se fosse criado dentro, voltaria a zero a cada volta. |
for (int i = 1; i <= 100; i++) | Passa por 1, 2, 3, …, 100. |
soma += i; | Soma o número da vez ao total (é o mesmo que soma = soma + i;). |
System.out.println(…) | Fora do laço: mostra o total uma vez, no fim. |
Nas primeiras voltas: soma = 0+1 = 1, depois 1+2 = 3, depois 3+3 = 6, depois 6+4 = 10… até 5050. O mesmo padrão serve para multiplicar (comece com 1, não com 0!), contar quantos números passam num teste ou juntar texto.
Padrão 2: repetir com fórmula (a tabuada)
A variável do laço pode entrar em contas dentro do corpo. A tabuada do 7 é 7 x i para i de 1 a 10:
public class Main {
public static void main(String[] args) {
int numero = 7;
for (int i = 1; i <= 10; i++) {
System.out.println(numero + " x " + i + " = " + (numero * i));
}
}
}
$ java Main.java 7 x 1 = 7 7 x 2 = 14 7 x 3 = 21 7 x 4 = 28 7 x 5 = 35 7 x 6 = 42 7 x 7 = 49 7 x 8 = 56 7 x 9 = 63 7 x 10 = 70
Os parênteses em (numero * i) são importantes: sem eles, o + do texto viria antes e o Java "colaria" os números em vez de multiplicar (veja Concatenação).
Missão: mude o programa para mostrar a tabuada do 9, de 9 x 1 = 9 até 9 x 10 = 90.
public class Main {
public static void main(String[] args) {
int numero = 7;
for (int i = 1; i <= 10; i++) {
System.out.println(numero + " x " + i + " = " + (numero * i));
}
}
}
public class Main {
public static void main(String[] args) {
int numero = 9;
for (int i = 1; i <= 10; i++) {
System.out.println(numero + " x " + i + " = " + (numero * i));
}
}
}
A variável do laço e o escopo
A variável criada no início do for (o int i) só existe dentro do laço: no cabeçalho e no corpo. Quando o laço termina, ela some. A região do código onde uma variável existe se chama escopo (do grego skopós, "alvo, o que se vê"). O tema completo tem aula própria em Escopo, no Nível 2.
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
System.out.println(i);
}
System.out.println("Depois do laço: " + i);
}
}
$ java Main.java
Main.java:6: error: cannot find symbol
System.out.println("Depois do laço: " + i);
^
symbol: variable i
location: class Main
1 error
error: compilation failed
Lendo a mensagem do javac (veja Lendo Erros do javac):
- Main.java:6:
- O arquivo e a linha do problema: a linha 6, o
printlndepois do laço. - error: cannot find symbol
- "Não encontro o símbolo": um nome que o compilador não conhece.
- ^
- A seta aponta para o nome desconhecido: o
i. - symbol: variable i
- O símbolo é uma variável chamada
i. - location: class Main
- Onde ele procurou: na classe
Main.
O programa não chega a rodar: nem o "1, 2, 3" aparece. Para o javac, na linha 6 o i já não existe mais. Se você precisa do valor depois do laço, declare a variável antes dele e, no for, só dê o valor inicial (sem o int):
public class Main {
public static void main(String[] args) {
int i;
for (i = 1; i <= 3; i++) {
System.out.println(i);
}
System.out.println("Depois do laço: " + i);
}
}
$ java Main.java 1 2 3 Depois do laço: 4 « o valor que fez a condição falhar
O lado bom do escopo: reaproveitar o nome
Como o i some no fim do laço, você pode criar outro i em outro laço logo abaixo, sem conflito:
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
System.out.println("Dentro: " + i);
}
for (int i = 10; i <= 12; i++) {
System.out.println("Outro laço: " + i);
}
}
}
$ java Main.java Dentro: 1 Dentro: 2 Dentro: 3 Outro laço: 10 Outro laço: 11 Outro laço: 12
O que não pode é criar o i do laço se já existir um i do lado de fora, ainda "vivo":
public class Main {
public static void main(String[] args) {
int i = 1;
for (int i = 0; i < 3; i++) {
System.out.println(i);
}
}
}
$ java Main.java
Main.java:4: error: variable i is already defined in method main(String[])
for (int i = 0; i < 3; i++) {
^
1 error
error: compilation failed
"A variável i já foi definida no método main". Troque o nome de uma delas, ou tire o int do for para reaproveitar a de fora.
Formas diferentes de escrever o cabeçalho
Duas variáveis no mesmo laço
O início e o passo aceitam várias partes separadas por vírgula. Aqui i sobe e j desce até se encontrarem:
public class Main {
public static void main(String[] args) {
for (int i = 0, j = 10; i < j; i++, j--) {
System.out.println("i = " + i + ", j = " + j);
}
}
}
$ java Main.java i = 0, j = 10 i = 1, j = 9 i = 2, j = 8 i = 3, j = 7 i = 4, j = 6
Vírgula separa as partes dentro do início ou do passo; ponto e vírgula separa o início, a condição e o passo. É útil, mas use com moderação: um cabeçalho difícil de ler esconde erros.
Partes vazias
As três partes são opcionais (os dois ; não):
for (; i <= 5; i++): sem início, usa umicriado antes.for (int i = 1; i <= 5; ): sem passo; aí o passo tem que estar no corpo, e vira umwhiledisfarçado.for (;;): sem condição nenhuma, é um laço infinito, igual awhile (true). Só termina combreak(veja break e continue) ou com Ctrl+C.
Com var
Desde o Java 10, dá para escrever for (var i = 1; i <= 5; i++): o Java descobre que i é int pelo valor 1 (veja var). Num for de contagem, int é tão curto quanto e mais claro; o var brilha mais no for-each.
for × while: qual usar
Todo for pode ser escrito como while e vice-versa. A escolha é sobre clareza: o leitor do seu código deve entender o laço de relance.
for | while | do-while | |
|---|---|---|---|
| Melhor quando | Você sabe quantas voltas (ou de onde até onde) | Repete até algo acontecer, sem contagem fixa | A primeira volta tem que acontecer sempre |
| Exemplos | De 1 a 10; cada posição de um array; tabuada | Juntar até a meta; ler até o usuário digitar "sair" | Menu; pedir um dado até ser válido |
| Início, condição e passo | Juntos no cabeçalho | Espalhados pelo código | Espalhados; condição no fim |
| Variável de controle | Some no fim do laço (se criada no cabeçalho) | Continua existindo depois | Continua existindo depois |
| Risco de esquecer o passo | Baixo: ele tem lugar marcado | Maior | Maior |
| Mínimo de voltas | 0 | 0 | 1 |
E para percorrer todos os itens de um array ou lista, sem precisar da posição, existe um quarto laço, ainda mais simples: o for-each.
Quando dá errado
public class Main {
public static void main(String[] args) {
for (int i = 0, i < 5, i++) {
System.out.println(i);
}
}
}
$ java Main.java
Main.java:3: error: ';' expected
for (int i = 0, i < 5, i++) {
^
Main.java:3: error: illegal start of type
for (int i = 0, i < 5, i++) {
^
2 errors
error: compilation failed
O que quer dizer: as três partes do for são separadas por ;. Com vírgulas, o javac acha que você está criando várias variáveis (int i = 0, i …) e se perde. O primeiro erro, ';' expected, é o que importa; o segundo é consequência dele. Corrija o primeiro e rode de novo.
Como consertar: for (int i = 0; i < 5; i++).
; a mais
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++); {
System.out.println("Volta " + i);
}
}
}
$ java Main.java
Main.java:4: error: cannot find symbol
System.out.println("Volta " + i);
^
symbol: variable i
location: class Main
1 error
error: compilation failed
O que aconteceu: o ; depois do ) é o corpo do for: um corpo vazio. O laço dá 5 voltas fazendo nada, e o i morre ali. As chaves que vêm depois viram um bloco solto, que roda uma vez, e dentro dele o i não existe mais. Por sorte, aqui o escopo transformou o engano num erro de compilação. Se o corpo não usasse o i, o programa rodaria o bloco uma vez só, sem nenhum aviso.
Como consertar: apague o ; entre o ) e a {.
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 5; i--) {
System.out.println("Volta " + i);
}
}
}
$ java Main.java Volta 1 Volta 0 Volta -1 Volta -2 Volta -3 Volta -4 « … e continua: -5, -6, -7 … ^CVolta -185299 « Ctrl+C depois de 1 segundo Volta -186748 Volta -186749 $ echo $? 130
O que aconteceu: o i começa em 1 e o passo i-- o diminui. Ele nunca vai passar de 5, então a condição i <= 5 é sempre verdadeira. Em um segundo, o programa chegou a quase -187 mil antes do Ctrl+C.
Como consertar: o passo precisa andar na direção que faz a condição ficar falsa. Subindo até 5: i++. Descendo: comece alto e teste com >=, como em for (int i = 5; i >= 1; i--).
for (int i = 1; i < 10; i++) vai de 1 a 9. for (int i = 0; i <= 10; i++) dá 11 voltas (de 0 a 10). Quando o número de voltas sair errado, confira o início (0 ou 1?) e o operador (< ou <=?). As duas combinações seguras são i = 1; i <= N e i = 0; i < N.
Referência
| Cabeçalho | Valores de i | Voltas |
|---|---|---|
for (int i = 1; i <= 5; i++) | 1, 2, 3, 4, 5 | 5 |
for (int i = 0; i < 5; i++) | 0, 1, 2, 3, 4 | 5 |
for (int i = 5; i >= 1; i--) | 5, 4, 3, 2, 1 | 5 |
for (int i = 0; i <= 10; i += 2) | 0, 2, 4, 6, 8, 10 | 6 |
for (int i = 1; i <= 100; i *= 10) | 1, 10, 100 | 3 |
for (char c = 'a'; c <= 'e'; c++) | a, b, c, d, e | 5 |
for (int i = 0, j = 10; i < j; i++, j--) | (0,10), (1,9) … (4,6) | 5 |
for (;;) | sem variável | infinitas (até break) |
Exercícios
1. Complete o cabeçalho
Complete para mostrar os números de 1 a 20:
2. De 5 em 5
Complete o passo para mostrar 0, 5, 10, 15, 20:
3. Contagem regressiva
Complete o início para mostrar 10, 9, 8, …, 1:
4. Quantas vezes o corpo de for (int i = 0; i < 10; i++) roda?
5. Em que ordem as partes do for rodam a cada volta (depois da primeira)?
6. Por que for (int i = 1; i <= 3; i++) { } System.out.println(i); não compila?
7. Qual laço combina melhor com "pedir a senha até a pessoa acertar"?
Missão final: some todos os números pares de 2 a 100 (2 + 4 + 6 + … + 100) e mostre Soma dos pares: seguido do total. Use um for. Há pelo menos dois jeitos: passo 2, ou passo 1 com um if testando i % 2 == 0.
public class Main {
public static void main(String[] args) {
int soma = 0;
// escreva o for aqui
System.out.println("Soma dos pares: " + soma);
}
}
public class Main {
public static void main(String[] args) {
int soma = 0;
for (int i = 2; i <= 100; i += 2) {
soma += i;
}
System.out.println("Soma dos pares: " + soma);
}
}
Resumo
for (início; condição; passo) { corpo }junta as três peças de um contador numa linha.- Ordem: início (uma vez) → condição → corpo → passo → condição → …
i = 1; i <= Nei = 0; i < Ndão N voltas. O segundo é o padrão para arrays.- O passo pode ser
i++,i--,i += 2,i *= 2… desde que leve a condição a ficar falsa. - Acumulador: crie antes do laço (
int soma = 0;) e atualize dentro (soma += i;). - A variável criada no cabeçalho só existe dentro do laço; usá-la depois dá
cannot find symbol. - Sabe quantas voltas?
for. Repete até algo acontecer?while. Precisa de uma volta garantida?do-while.