Try-Catch, exceções comuns e desafios práticos com ArrayList e HashMap
Uma exceção é um evento inesperado que ocorre durante a execução do programa e interrompe o fluxo normal. Sem tratamento, o programa simplesmente para e imprime uma mensagem de erro no terminal.
Sem tratamento, este código para abruptamente:
public class SemTratamento {
public static void main(String[] args) {
int[] numeros = {10, 20, 30};
System.out.println(numeros[5]); // índice 5 não existe!
}
}
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3
at SemTratamento.main(SemTratamento.java:4)
O bloco try-catch envolve o código que pode falhar e define o que fazer quando a falha ocorrer — sem derrubar o programa.
public class AnatomiatryCatch {
public static void main(String[] args) {
try {
// código que pode lançar exceção
int resultado = 10 / 0;
System.out.println("Resultado: " + resultado);
} catch (ArithmeticException e) {
// executado apenas se a exceção ocorrer
System.out.println("Erro: " + e.getMessage());
} finally {
// executado SEMPRE, com ou sem exceção (opcional)
System.out.println("Bloco finally executado.");
}
System.out.println("Programa continua normalmente.");
}
}
Erro: / by zero
Bloco finally executado.
Programa continua normalmente.
💡 O bloco finally é opcional, mas quando presente é sempre executado — mesmo que o catch seja acionado. Usado normalmente para fechar arquivos, conexões ou o Scanner.
| Exceção | Quando ocorre | Exemplo |
|---|---|---|
ArithmeticException |
Divisão por zero | int x = 5 / 0; |
ArrayIndexOutOfBoundsException |
Índice de array inexistente | arr[10] quando o array tem 3 elementos |
NullPointerException |
Usar objeto que é null |
String s = null; s.length(); |
NumberFormatException |
Converter texto inválido em número | Integer.parseInt("abc"); |
InputMismatchException |
Usuário digita tipo errado no Scanner | Scanner esperava int, recebeu "abc" |
StringIndexOutOfBoundsException |
Índice inválido em String | "Java".charAt(10); |
Um único try pode ter vários catch para tratar tipos diferentes de exceção:
public class MultiplosCatch {
public static void main(String[] args) {
String[] textos = {"42", null, "abc"};
for (String texto : textos) {
try {
int numero = Integer.parseInt(texto); // pode lançar NumberFormatException ou NullPointerException
System.out.println("Número válido: " + numero);
} catch (NumberFormatException e) {
System.out.println("Não é um número: \"" + texto + "\"");
} catch (NullPointerException e) {
System.out.println("Texto nulo — não é possível converter.");
}
}
}
}
Número válido: 42
Texto nulo — não é possível converter.
Não é um número: "abc"
O erro mais comum ao usar Scanner é o usuário digitar um texto quando o programa espera um número. O InputMismatchException trata exatamente isso:
import java.util.Scanner;
import java.util.InputMismatchException;
public class EntradaSegura {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int idade = 0;
boolean entradaValida = false;
while (!entradaValida) {
System.out.print("Digite sua idade: ");
try {
idade = sc.nextInt();
entradaValida = true; // só chega aqui se nextInt() não lançou exceção
} catch (InputMismatchException e) {
System.out.println("Erro: digite apenas números inteiros.");
sc.nextLine(); // descarta o texto inválido que ficou no buffer
}
}
System.out.println("Idade registrada: " + idade);
sc.close();
}
}
Digite sua idade: abc
Erro: digite apenas números inteiros.
Digite sua idade: vinte
Erro: digite apenas números inteiros.
Digite sua idade: 25
Idade registrada: 25
⚠ Por que sc.nextLine() depois do catch? Quando nextInt() falha, o texto inválido permanece no buffer do Scanner. Se não for descartado com nextLine(), o próximo nextInt() lê o mesmo texto inválido de novo — criando um loop infinito.
Sistema de cadastro que combina ArrayList, HashMap, Scanner e tratamento de erros. Note como o try-catch protege a leitura do menu sem derrubar o programa:
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.InputMismatchException;
public class cadastroInterativoAlunos_ArrayList_HashMap {
public static void main(String[] args) {
ArrayList<HashMap<String, String>> cadastro = new ArrayList<>();
Scanner entrada = new Scanner(System.in);
while (true) {
System.out.println("=== SISTEMA DE CADASTRO ===");
System.out.println("1. Cadastrar aluno");
System.out.println("2. Listar alunos");
System.out.println("3. Buscar aluno");
System.out.println("4. Sair");
System.out.print("Escolha: ");
int opcao;
try {
opcao = entrada.nextInt();
entrada.nextLine(); // consome o "\n" que sobra do nextInt()
} catch (InputMismatchException e) {
System.out.println("Opção inválida. Digite um número de 1 a 4.");
entrada.nextLine(); // descarta o texto inválido do buffer
continue; // volta ao início do while e exibe o menu de novo
}
if (opcao == 1) {
System.out.print("Digite o nome do aluno: ");
String nomeAluno = entrada.nextLine();
System.out.print("Digite a matrícula do aluno: ");
String matricula = entrada.nextLine();
System.out.print("Digite a turma do aluno: ");
String turma = entrada.nextLine();
System.out.print("Digite o período do aluno: ");
String periodo = entrada.nextLine();
HashMap<String, String> aluno = new HashMap<>();
aluno.put("nome", nomeAluno);
aluno.put("matricula", matricula);
aluno.put("turma", turma);
aluno.put("periodo", periodo);
cadastro.add(aluno);
System.out.println("Aluno cadastrado com sucesso!");
} else if (opcao == 2) {
if (cadastro.isEmpty()) {
System.out.println("Nenhum aluno cadastrado.");
} else {
System.out.println("Cadastro de Alunos:");
for (HashMap<String, String> aluno : cadastro) {
System.out.println("Nome: " + aluno.get("nome")
+ " | Matrícula: " + aluno.get("matricula")
+ " | Turma: " + aluno.get("turma")
+ " | Período: " + aluno.get("periodo"));
}
}
} else if (opcao == 3) {
System.out.print("Digite o nome do aluno a buscar: ");
String busca = entrada.nextLine();
boolean encontrado = false;
for (HashMap<String, String> aluno : cadastro) {
if (aluno.get("nome").equalsIgnoreCase(busca)) {
System.out.println("Nome: " + aluno.get("nome")
+ " | Matrícula: " + aluno.get("matricula")
+ " | Turma: " + aluno.get("turma")
+ " | Período: " + aluno.get("periodo"));
encontrado = true;
}
}
if (!encontrado) {
System.out.println("Aluno não encontrado.");
}
} else if (opcao == 4) {
System.out.println("Encerrando...");
break;
} else {
System.out.println("Opção inválida. Digite um número de 1 a 4.");
}
}
entrada.close();
}
}
=== SISTEMA DE CADASTRO ===
1. Cadastrar aluno
2. Listar alunos
3. Buscar aluno
4. Sair
Escolha: menu
Opção inválida. Digite um número de 1 a 4.
=== SISTEMA DE CADASTRO ===
1. Cadastrar aluno
2. Listar alunos
3. Buscar aluno
4. Sair
Escolha: 1
Digite o nome do aluno: Ana Silva
Digite a matrícula do aluno: 2024001
Digite a turma do aluno: CC-03
Digite o período do aluno: 3º
Aluno cadastrado com sucesso!
Por que o continue depois do catch? O continue pula o restante do corpo do while e volta imediatamente ao início — exibindo o menu de novo. Sem ele, o código continuaria tentando executar os if/else com uma variável opcao não inicializada.
Escreva um programa que leia dois números inteiros do teclado e exiba o resultado da divisão. Use try-catch para tratar dois erros possíveis:
O programa deve continuar pedindo os números até que uma divisão válida seja realizada.
import java.util.Scanner;
import java.util.InputMismatchException;
public class DivisaoSegura {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (true) {
try {
System.out.print("Digite o dividendo: ");
int dividendo = sc.nextInt();
System.out.print("Digite o divisor: ");
int divisor = sc.nextInt();
int resultado = dividendo / divisor; // lança ArithmeticException se divisor == 0
System.out.println("Resultado: " + dividendo + " / " + divisor + " = " + resultado);
break; // divisão válida — encerra o loop
} catch (ArithmeticException e) {
System.out.println("Erro: divisão por zero não é permitida.");
sc.nextLine();
} catch (InputMismatchException e) {
System.out.println("Erro: digite apenas números inteiros.");
sc.nextLine(); // descarta o texto inválido do buffer
}
}
sc.close();
}
}
Digite o dividendo: dez
Erro: digite apenas números inteiros.
Digite o dividendo: 10
Digite o divisor: 0
Erro: divisão por zero não é permitida.
Digite o dividendo: 10
Digite o divisor: 3
Resultado: 10 / 3 = 3
Dado o array abaixo, escreva um programa que:
try-catch para capturar ArrayIndexOutOfBoundsException e exibir uma mensagem amigávelString[] cidades = {"Natal", "Recife", "Fortaleza", "João Pessoa", "Maceió"};
import java.util.Scanner;
import java.util.InputMismatchException;
public class AcessoSeguroArray {
public static void main(String[] args) {
String[] cidades = {"Natal", "Recife", "Fortaleza", "João Pessoa", "Maceió"};
Scanner sc = new Scanner(System.in);
System.out.println("O array tem " + cidades.length + " cidades (índices 0 a " + (cidades.length - 1) + ").");
while (true) {
System.out.print("Digite um índice: ");
try {
int idx = sc.nextInt();
System.out.println("Cidade encontrada: " + cidades[idx]); // lança ArrayIndexOutOfBoundsException se inválido
break;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Índice inválido. Escolha entre 0 e " + (cidades.length - 1) + ".");
} catch (InputMismatchException e) {
System.out.println("Digite apenas números inteiros.");
sc.nextLine();
}
}
sc.close();
}
}
O array tem 5 cidades (índices 0 a 4).
Digite um índice: 10
Índice inválido. Escolha entre 0 e 4.
Digite um índice: -1
Índice inválido. Escolha entre 0 e 4.
Digite um índice: 2
Cidade encontrada: Fortaleza
Crie uma lista de compras usando ArrayList<HashMap<String, String>> com pelo menos 5 produtos (nome e preço). Em seguida:
import java.util.ArrayList;
import java.util.HashMap;
public class ListaCompras {
public static void main(String[] args) {
ArrayList<HashMap<String, String>> compras = new ArrayList<>();
String[][] itens = {
{"Arroz 5kg", "28.90"},
{"Feijão 1kg", "9.50"},
{"Frango 2kg", "32.00"},
{"Queijo 500g", "22.00"},
{"Detergente", "4.80"},
{"Sabão em pó", "18.50"},
{"Café 500g", "15.00"},
{"Shampoo", "24.99"},
{"Leite 1L", "7.50"},
{"Macarrão", "6.90"}
};
for (String[] item : itens) {
HashMap<String, String> produto = new HashMap<>();
produto.put("nome", item[0]);
produto.put("preco", item[1]);
compras.add(produto);
}
// Exibindo todos
System.out.println("=== LISTA DE COMPRAS ===");
double total = 0;
for (HashMap<String, String> p : compras) {
double preco = Double.parseDouble(p.get("preco"));
System.out.printf("%-15s R$ %.2f%n", p.get("nome"), preco);
total += preco;
}
System.out.printf("TOTAL: R$ %.2f%n", total);
// Produtos acima de R$ 50 — nenhum neste exemplo, mas a lógica está correta
System.out.println("Produtos acima de R$ 20,00:");
for (HashMap<String, String> p : compras) {
if (Double.parseDouble(p.get("preco")) > 20.00) {
System.out.println("- " + p.get("nome"));
}
}
}
}
=== LISTA DE COMPRAS ===
Arroz 5kg R$ 28.90
Feijão 1kg R$ 9.50
Frango 2kg R$ 32.00
Queijo 500g R$ 22.00
Detergente R$ 4.80
Sabão em pó R$ 18.50
Café 500g R$ 15.00
Shampoo R$ 24.99
Leite 1L R$ 7.50
Macarrão R$ 6.90
TOTAL: R$ 170.09
Produtos acima de R$ 20,00:
- Arroz 5kg
- Frango 2kg
- Queijo 500g
- Shampoo
Crie um ArrayList<HashMap<String, String>> representando um estoque com pelo menos 4 produtos (nome, quantidade, preço). Implemente:
.put()
import java.util.ArrayList;
import java.util.HashMap;
public class Estoque {
public static void main(String[] args) {
ArrayList<HashMap<String, String>> estoque = new ArrayList<>();
String[][] dados = {
{"Notebook", "15", "3500.00"},
{"Mouse", "40", "80.00"},
{"Teclado", "25", "150.00"},
{"Monitor", "10", "900.00"}
};
for (String[] d : dados) {
HashMap<String, String> p = new HashMap<>();
p.put("nome", d[0]);
p.put("quantidade", d[1]);
p.put("preco", d[2]);
estoque.add(p);
}
// Exibir estoque inicial
System.out.println("=== ESTOQUE INICIAL ===");
for (HashMap<String, String> p : estoque) {
System.out.printf("%-12s Qtd: %-5s Preço: R$ %s%n",
p.get("nome"), p.get("quantidade"), p.get("preco"));
}
// Buscar produto
String busca = "Mouse";
System.out.println("\nBuscando: " + busca);
for (HashMap<String, String> p : estoque) {
if (p.get("nome").equalsIgnoreCase(busca)) {
System.out.println("Encontrado — Quantidade atual: " + p.get("quantidade"));
}
}
// Atualizar quantidade do Mouse
for (HashMap<String, String> p : estoque) {
if (p.get("nome").equalsIgnoreCase("Mouse")) {
p.put("quantidade", "55");
System.out.println("Quantidade do Mouse atualizada para 55.");
}
}
// Estoque atualizado
System.out.println("\n=== ESTOQUE ATUALIZADO ===");
for (HashMap<String, String> p : estoque) {
System.out.printf("%-12s Qtd: %-5s Preço: R$ %s%n",
p.get("nome"), p.get("quantidade"), p.get("preco"));
}
}
}
=== ESTOQUE INICIAL ===
Notebook Qtd: 15 Preço: R$ 3500.00
Mouse Qtd: 40 Preço: R$ 80.00
Teclado Qtd: 25 Preço: R$ 150.00
Monitor Qtd: 10 Preço: R$ 900.00
Buscando: Mouse
Encontrado — Quantidade atual: 40
Quantidade do Mouse atualizada para 55.
=== ESTOQUE ATUALIZADO ===
Notebook Qtd: 15 Preço: R$ 3500.00
Mouse Qtd: 55 Preço: R$ 80.00
Teclado Qtd: 25 Preço: R$ 150.00
Monitor Qtd: 10 Preço: R$ 900.00
Questões práticas sobre try-catch e tratamento de exceções:
Reforce o conteúdo desta aula com mais dois exercícios práticos: