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.

Você vai aprender
  • 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 symbol quando você a usa fora dele.
  • Quando usar for e quando usar while.

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:

  1. Começa a contar do 1.
  2. Antes de cada flexão, verifica se ainda não passou de 10.
  3. 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 whileCom 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 der false, 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.
Por que 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:

  1. Início (int i = 1): uma vez só.
  2. Condição (i <= 5): se for false, pula para depois da } e acabou.
  3. Corpo: mostra "Volta i".
  4. Passo (i++): soma 1.
  5. Volta ao passo 2.
MomentoiCondição i <= 5Acontece
Início1trueVolta 1, depois i++
2º teste2trueVolta 2, depois i++
3º teste3trueVolta 3, depois i++
4º teste4trueVolta 4, depois i++
5º teste5trueVolta 5, depois i++
6º teste6falseSai 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
LinhaO 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.

Este código tem um erro de propósito
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 println depois 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 um i criado antes.
  • for (int i = 1; i <= 5; ): sem passo; aí o passo tem que estar no corpo, e vira um while disfarçado.
  • for (;;): sem condição nenhuma, é um laço infinito, igual a while (true). Só termina com break (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.

forwhiledo-while
Melhor quandoVocê sabe quantas voltas (ou de onde até onde)Repete até algo acontecer, sem contagem fixaA primeira volta tem que acontecer sempre
ExemplosDe 1 a 10; cada posição de um array; tabuadaJuntar até a meta; ler até o usuário digitar "sair"Menu; pedir um dado até ser válido
Início, condição e passoJuntos no cabeçalhoEspalhados pelo códigoEspalhados; condição no fim
Variável de controleSome no fim do laço (se criada no cabeçalho)Continua existindo depoisContinua existindo depois
Risco de esquecer o passoBaixo: ele tem lugar marcadoMaiorMaior
Mínimo de voltas001

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

Vírgulas no lugar de ponto e vírgula
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++).

"cannot find symbol" por causa de um ; 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 {.

O passo vai na direção errada
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--).

Uma volta a mais ou a menos

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çalhoValores de iVoltas
for (int i = 1; i <= 5; i++)1, 2, 3, 4, 55
for (int i = 0; i < 5; i++)0, 1, 2, 3, 45
for (int i = 5; i >= 1; i--)5, 4, 3, 2, 15
for (int i = 0; i <= 10; i += 2)0, 2, 4, 6, 8, 106
for (int i = 1; i <= 100; i *= 10)1, 10, 1003
for (char c = 'a'; c <= 'e'; c++)a, b, c, d, e5
for (int i = 0, j = 10; i < j; i++, j--)(0,10), (1,9) … (4,6)5
for (;;)sem variávelinfinitas (até break)

Exercícios

1. Complete o cabeçalho

Complete para mostrar os números de 1 a 20:

for (int i = 1; ; i++)

2. De 5 em 5

Complete o passo para mostrar 0, 5, 10, 15, 20:

for (int i = 0; i <= 20; )

3. Contagem regressiva

Complete o início para mostrar 10, 9, 8, …, 1:

for (; i >= 1; i--)

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 <= N e i = 0; i < N dã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.