Especialização em Sistemas com Java 21 LTS • Módulo de Fundamentos


🗺️ Mapa Conceitual do Tópico

flowchart TD
    A["Início do Laço"] --> B{"Tipo de Estrutura"}
    
    B -->|Pré-Testado| C["while (condicao)"]
    B -->|Determinístico| D["for (init; teste; passo)"]
    B -->|Coleções / Arrays| E["for (Tipo item : colecao)"]
    B -->|Pós-Testado| F["do { ... } while (condicao);"]
    
    C & D & E --> G{"Condição Verdadeira?"}
    G -->|Sim| H["Executa Corpo da Iteração"]
    G -->|Não| I["Sai do Laço"]
    
    F --> H
    H --> J{"Controle de Fluxo"}
    J -->|continue| G
    J -->|break| I
    J -->|break rotulado| K["Sai de Múltiplos Laços (outer)"]
    
    style A fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
    style B fill:#fff3e0,stroke:#ff9800,stroke-width:2px
    style E fill:#ede7f6,stroke:#7e57c2,stroke-width:2px
    style K fill:#ffebee,stroke:#f44336,stroke-width:2px

🔁 1. A Tríade Tradicional de Laços no Java

As instruções de repetição permitem executar blocos de código repetidamente com base em critérios booleanos. No nível do bytecode da JVM, todos os laços são traduzidos em sequências de instruções condicionais de salto (goto, ifeq, if_icmplt).

1. while: Repetição Pré-Testada

Utilizado quando a quantidade exata de iterações não é conhecida previamente e depende de um evento externo (ex.: consumo de socket, leitura de arquivo até EOF, polling de filas):

while (filaMensagens.hasPendingMessages()) {
    Mensagem msg = filaMensagens.poll();
    processar(msg);
}

Se a condição inicial for falsa, o corpo do laço nunca é executado.

2. do-while: Repetição Pós-Testada

Garante que o bloco de instruções seja executado obrigatoriamente pelo menos uma vez, avaliando o predicado apenas ao final de cada ciclo:

int tentativas = 0;
boolean conexaoEstabelecida = false;
do {
    tentativas++;
    conexaoEstabelecida = conectarSocket();
} while (!conexaoEstabelecida && tentativas < 3);

3. for Clássico: Controle Baseado em Índices

Ideal para iterações numéricas com contador finito e passos regulares:

for (int i = 0; i < tamanho; i += 2) {
    System.out.printf("Processando índice par: %d%n", i);
}

📦 2. O Laço Moderno for-each e a Interface Iterable<T>

Introduzido no Java 5 e amplamente utilizado até o Java 21, o for-each (enhanced for loop) oculta a complexidade mecânica de iteradores e índices de vetores.

Desaçucaramento Sintático pelo Compilador:

  • Sobre Matrizes (T[]): O compilador converte internamente em um laço indexado for (int i = 0; i < arr.length; i++).
  • Sobre Coleções (Iterable<T>): O compilador gera código equivalente a:
    for (Iterator<Transacao> it = lista.iterator(); it.hasNext(); ) {
        Transacao tx = it.next();
        // Corpo do loop
    }
    

⚠️ O Perigo do ConcurrentModificationException

Nunca adicione ou remova elementos diretamente da coleção enquanto a percorre em um for-each. Para remoções seguras durante a iteração:

  1. Utilize it.remove() diretamente sobre o Iterator.
  2. Utilize o método funcional lista.removeIf(p -> p.isExpirada()).

🕹️ 3. Controle Fino: break, continue e Laços Rotulados (Labels)

Quando operamos com matrizes multidimensionais ou algoritmos de busca aninhados, break e continue padrão afetam apenas o laço imediatamente interno.

Laços Rotulados (Labeled Statements)

O Java permite nomear blocos repetitivos com rótulos seguidos de dois-pontos (label:), viabilizando a interrupção imediata de toda a pilha de iterações sem a necessidade de bandeiras booleanas (boolean flagEncontrado):

buscaMatriz:
for (int linha = 0; linha < matriz.length; linha++) {
    for (int col = 0; col < matriz[linha].length; col++) {
        if (matriz[linha][col] == ALVO_CRITICO) {
            System.out.printf("Alvo localizado em [%d, %d]! Abortando busca.%n", linha, col);
            break buscaMatriz; // Encerra o loop externo imediatamente
        }
    }
}

📊 4. Matriz Comparativa de Estruturas Repetitivas

Estrutura Momento da Avaliação Garantia Mínima de Execução Manutenção de Estado do Índice Caso de Uso Ideal
while Antes da 1ª iteração 0 vezes Variável declarada externamente Fluxos de entrada contínuos, leituras assíncronas
do-while Ao final de cada iteração 1 vez Variável declarada externamente Menus de console, handshakes de rede, retries
for tradicional Antes da 1ª iteração 0 vezes Escopo restrito ao laço Varredura com saltos customizados ou ordem reversa
for-each Pela interface Iterator 0 vezes Nenhum (apenas o elemento) Leitura sequencial limpa de coleções e arrays

⚡ 5. Otimizações da JVM: Unrolling e Custo de Boxing

Em laços críticos de alta taxa de transferência (HFT, processamento gráfico, Big Data):

  1. Loop Unrolling: O compilador Just-In-Time (C2 JIT) pode desenrolar laços pequenos (ex: 4 em 4 iterações) para eliminar instruções jump e otimizar o pipeline da CPU.
  2. Evite Boxing/Unboxing em Laços: Declarar o acumulador como Double soma = 0.0; força a criação de milhares de instâncias wrappers na Heap a cada soma += valor;. Use sempre primitivos (double soma = 0.0;).

💻 6. Código de Demonstração Corporativo (Java 21 LTS)

package com.empresa.fundamentos;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

/**
 * Processador em lote com tentativas de conexão (do-while) e varredura rotulada (labeled break).
 */
public class ProcessadorLoteOrdens {

    public record OrdemServico(long id, String cliente, BigDecimal valor, boolean temFraude) {}

    public static boolean tentarHandshakeServidor(int tentativaMax) {
        int attempt = 0;
        boolean conectado = false;
        do {
            attempt++;
            System.out.printf("   [REDE] Tentativa de conexão ao cluster RPC (%d/%d)...%n", attempt, tentativaMax);
            if (attempt == 2) { // Simulação: conecta na 2ª tentativa
                conectado = true;
            }
        } while (!conectado && attempt < tentativaMax);
        return conectado;
    }

    public static void main(String[] args) {
        System.out.println("================================================================================");
        System.out.println("           PROCESSAMENTO DE LOTES FINANCEIROS COM CONTROLE DE LAÇOS             ");
        System.out.println("================================================================================");

        if (!tentarHandshakeServidor(3)) {
            System.err.println("Falha catastrófica: Servidor de liquidação indisponível.");
            return;
        }

        // Simulação de lotes de ordens em matriz bidimensional (Lotes x Ordens)
        OrdemServico[][] matrizLotes = {
            { new OrdemServico(101, "Alpha Tech", new BigDecimal("1500.00"), false),
              new OrdemServico(102, "Beta Corp", new BigDecimal("3200.00"), false) },
            { new OrdemServico(201, "Gama Log", new BigDecimal("8900.00"), true), // Fraude detectada
              new OrdemServico(202, "Delta S/A", new BigDecimal("4100.00"), false) },
            { new OrdemServico(301, "Epsilon Inc", new BigDecimal("12000.00"), false) }
        };

        BigDecimal volumeLiquidado = BigDecimal.ZERO;
        int totalProcessadas = 0;

        processamentoLotes:
        for (int loteIdx = 0; loteIdx < matrizLotes.length; loteIdx++) {
            System.out.printf("🚀 Iniciando processamento do Lote #%d...%n", loteIdx + 1);

            for (OrdemServico ordem : matrizLotes[loteIdx]) {
                if (ordem.temFraude()) {
                    System.out.printf("🚨 [SEGURANÇA] Fraude na ordem #%d (%s)! Abortando processamento geral.%n",
                            ordem.id(), ordem.cliente());
                    break processamentoLotes; // Interrompe o loop externo
                }

                volumeLiquidado = volumeLiquidado.add(ordem.valor());
                totalProcessadas++;
                System.out.printf("   ✅ Ordem #%d aprovada - Cliente: %-12s | Valor: R$ %10.2f%n",
                        ordem.id(), ordem.cliente(), ordem.valor());
            }
        }

        System.out.println("--------------------------------------------------------------------------------");
        System.out.printf("Total de Ordens Liquidadas com Sucesso: %d%n", totalProcessadas);
        System.out.printf("Volume Financeiro Total Movimentado   : R$ %,10.2f%n", volumeLiquidado);
        System.out.println("================================================================================");
    }
}