Java Essencial: Controle de fluxo com if/else, switch e expressões condicionais

Capítulo 7

Tempo estimado de leitura: 7 minutos

+ Exercício

O que é controle de fluxo (decisão)

Controle de fluxo é o conjunto de estruturas que permite ao programa escolher caminhos diferentes de execução com base em condições. Em Java, as decisões mais comuns são feitas com if/else, switch e, em casos pontuais, com a expressão condicional (operador ternário ?:). O objetivo é transformar regras de negócio (ex.: “se renda for maior que X, então alíquota é Y”) em código claro, testável e fácil de manter.

Decisões com if/else

Quando usar

  • Quando a condição é booleana e pode envolver intervalos, comparações e combinações (ex.: faixa de valores, múltiplos critérios).
  • Quando você precisa de lógica mais flexível do que uma simples comparação de igualdade.

Estrutura básica

if (condicao) {    // caminho A} else {    // caminho B}

Você pode encadear múltiplas alternativas com else if:

if (condicao1) {    // A} else if (condicao2) {    // B} else {    // C (padrão)}

Boas práticas para evitar aninhamento excessivo

  • Preferir “guard clauses” (retornos antecipados) em métodos: reduzem níveis de indentação e deixam as regras mais lineares.
  • Extrair condições para variáveis booleanas com nomes claros: melhora legibilidade e facilita testes manuais.
  • Ordenar faixas do mais específico para o mais geral (ou do menor para o maior, dependendo da regra), garantindo que cada caso seja alcançável.

Exemplo prático: validação com guard clauses

Imagine uma regra: só aprovar um cadastro se idade for válida e o e-mail não estiver vazio.

static boolean aprovarCadastro(int idade, String email) {    if (idade < 0 || idade > 130) {        return false;    }    if (email == null || email.isBlank()) {        return false;    }    return true;}

Note como o método evita if aninhados. Cada regra “barra” o fluxo cedo, e o final fica simples.

Passo a passo: regra de faixa de imposto (simples)

Vamos criar uma regra didática de imposto por faixas (valores fictícios):

Continue em nosso aplicativo e ...
  • Ouça o áudio com a tela desligada
  • Ganhe Certificado após a conclusão
  • + de 5000 cursos para você explorar!
ou continue lendo abaixo...
Download App

Baixar o aplicativo

  • Até 2000.00: isento
  • De 2000.01 até 5000.00: 10%
  • Acima de 5000.00: 20%

Passo 1: Defina as entradas e saídas (renda → imposto).

Passo 2: Ordene as condições por faixa.

Passo 3: Calcule e retorne o imposto.

static double calcularImposto(double renda) {    if (renda <= 2000.00) {        return 0.0;    } else if (renda <= 5000.00) {        return renda * 0.10;    } else {        return renda * 0.20;    }}

Passo 4: Faça testes manuais com valores de fronteira (ver seção “Testes manuais”).

Decisões com switch

Quando usar

  • Quando você escolhe um caminho com base em um valor discreto (ex.: opção de menu, categoria, código).
  • Quando a comparação é por igualdade (um valor entre alternativas).

O switch tradicional funciona bem para menus e mapeamentos simples. Versões modernas do Java também oferecem formas mais expressivas, como switch com seta (->) e switch como expressão (retornando valor), quando disponíveis no seu JDK.

Switch tradicional (com break)

Sem break, ocorre “fall-through” (o fluxo continua no próximo case). Em geral, isso é fonte de bugs em menus, então use break quando cada caso deve ser exclusivo.

static String nomeDoDia(int dia) {    switch (dia) {        case 1:            return "Segunda";        case 2:            return "Terça";        case 3:            return "Quarta";        default:            return "Inválido";    }}

Como cada case retorna, não é necessário break neste exemplo.

Switch moderno com seta (mais legível)

Em JDKs mais recentes, você pode usar a forma com seta, que evita break e reduz erros de fall-through:

static String categoriaPorCodigo(int codigo) {    return switch (codigo) {        case 1 -> "Básico";        case 2 -> "Intermediário";        case 3 -> "Avançado";        default -> "Desconhecido";    };}

Perceba que aqui o switch é uma expressão: ele produz um valor que você retorna diretamente.

Switch moderno com bloco e yield

Quando um caso precisa de mais de uma instrução (ex.: validar, calcular, montar texto), você pode usar bloco e yield para devolver o valor daquele caso:

static String mensagemDeMenu(int opcao) {    return switch (opcao) {        case 1 -> "Listar itens";        case 2 -> {            String msg = "Cadastrar item";            yield msg;        }        case 3 -> "Sair";        default -> "Opção inválida";    };}

Exemplo prático: menu de console (estrutura de decisão)

Este exemplo foca na decisão (não em loops). Você lê uma opção e decide a ação:

import java.util.Scanner;public class MenuSimples {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        System.out.println("1 - Consultar saldo");        System.out.println("2 - Depositar");        System.out.println("3 - Sair");        System.out.print("Escolha: ");        int opcao = sc.nextInt();        String acao = switch (opcao) {            case 1 -> "Consultando saldo...";            case 2 -> "Iniciando depósito...";            case 3 -> "Encerrando...";            default -> "Opção inválida.";        };        System.out.println(acao);        sc.close();    }}

Dica: se seu JDK não suportar a forma moderna, use o switch tradicional com case e break.

Operador ternário (expressão condicional ?:)

Quando usar (uso criterioso)

  • Para escolhas simples entre dois valores.
  • Quando melhora a legibilidade e evita um if/else muito curto.

Evite ternários aninhados e expressões longas: isso costuma piorar a leitura e dificultar depuração.

Exemplo simples

static String classificarIdade(int idade) {    return (idade >= 18) ? "Maior de idade" : "Menor de idade";}

Comparação: if/else vs ternário

Se você precisa executar múltiplas ações (imprimir, calcular, validar, registrar), prefira if/else. Se é apenas escolher um valor, o ternário pode ser adequado.

// Bom uso: escolher um valordouble desconto = (clienteVip) ? 0.15 : 0.05;// Evite: ternário com lógica extensa e difícil de lerdouble taxa = (renda <= 2000) ? 0 : (renda <= 5000) ? 0.10 : 0.20;

No segundo caso, um if/else if/else tende a ficar mais claro.

Organizando regras com clareza

1) Nomeie as condições

boolean isIsento = renda <= 2000.00;boolean isFaixaIntermediaria = renda <= 5000.00;

Isso ajuda a “ler” a regra como texto.

2) Prefira tabelas mentais (faixas) e valide fronteiras

Para regras por faixa, escreva primeiro as fronteiras e decida se os limites são inclusivos (<=) ou exclusivos (<). Inconsistências aqui geram bugs difíceis (ex.: 2000.00 cair em duas faixas ou em nenhuma).

3) Evite duplicação de condições

Se você já garantiu um intervalo em um if, não repita a mesma checagem no próximo ramo.

// Menos claroif (renda > 2000 && renda <= 5000) { ... } else if (renda > 5000) { ... }// Mais claro (após o primeiro if, renda > 2000 já é verdade)if (renda <= 2000) { ... } else if (renda <= 5000) { ... } else { ... }

Exercícios (regras de negócio simples)

Exercício 1: Faixas de imposto (com valor de fronteira)

Implemente calcularImposto com as faixas:

  • Até 1500.00: 0%
  • De 1500.01 até 3000.00: 8%
  • De 3000.01 até 6000.00: 15%
  • Acima de 6000.00: 22%

Requisitos:

  • Se renda for negativa, retorne -1 para indicar erro.
  • Use if/else if/else sem aninhamento.

Exercício 2: Categoria por idade (if/else)

Crie categoria(int idade):

  • idade < 0: “Inválida”
  • 0 a 12: “Infantil”
  • 13 a 17: “Juvenil”
  • 18 a 59: “Adulto”
  • 60+: “Sênior”

Requisito: use variáveis booleanas nomeadas para pelo menos duas faixas, para treinar legibilidade.

Exercício 3: Menu de console (switch)

Faça um programa que leia uma opção e imprima:

  • 1: “Cadastrar”
  • 2: “Listar”
  • 3: “Atualizar”
  • 4: “Remover”
  • 0: “Sair”
  • Outro: “Opção inválida”

Requisitos:

  • Implemente com switch.
  • Se possível no seu JDK, use switch como expressão para retornar a mensagem.

Exercício 4: Ternário com critério

Crie rotuloAprovacao(double nota):

  • Se nota >= 7: “Aprovado”
  • Senão: “Reprovado”

Requisito: use operador ternário. Depois, reescreva com if/else e compare qual ficou mais legível para você.

Testes manuais: como validar caminhos (checklist)

Antes de automatizar testes, treine validar o controle de fluxo com uma tabela de casos. Foque em fronteiras e valores típicos.

Exemplo de tabela de testes: imposto por faixas

Entrada (renda)Faixa esperadaSaída esperada
-10.00Erro-1
0.000%0.00
1500.000%0.00
1500.018%120.0008
3000.008%240.00
3000.0115%450.0015
6000.0015%900.00
6000.0122%1320.0022

Observação: ao fazer testes manuais com double, considere formatar a saída para duas casas decimais ao imprimir, para facilitar conferência visual.

Checklist rápido

  • Testei valores exatamente nos limites (ex.: 1500.00, 1500.01)?
  • Testei um valor bem dentro de cada faixa?
  • Existe algum valor que não cai em nenhum ramo?
  • Existe algum ramo inalcançável por causa da ordem das condições?
  • Em switch tradicional, não esqueci break quando necessário?

Agora responda o exercício sobre o conteúdo:

Em uma regra de imposto por faixas usando if/else if/else, qual estrutura tende a ficar mais clara e evita duplicar condições desnecessárias?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

Após o primeiro if falhar, certas condições já estão garantidas (por exemplo, renda > 2000), então basta checar o próximo limite superior. Isso reduz duplicação e melhora a legibilidade.

Próximo capitúlo

Java Essencial: Laços de repetição (for, while, do-while) e for-each

Arrow Right Icon
Capa do Ebook gratuito Java Essencial: Fundamentos da Linguagem e do Ecossistema (JDK, IDE, Maven)
39%

Java Essencial: Fundamentos da Linguagem e do Ecossistema (JDK, IDE, Maven)

Novo curso

18 páginas

Baixe o app para ganhar Certificação grátis e ouvir os cursos em background, mesmo com a tela desligada.