Exceções Personalizadas
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 60 de 87.
As exceções integradas do Java cobrem muitos cenários de erro comuns, mas às vezes você precisa de exceções que sejam específicas para o domínio da sua aplicação. Exceções personalizadas permitem que você crie tipos de erro significativos que comunicam claramente o que deu errado.
Para criar uma exceção personalizada, basta estender uma classe de exceção existente. Para uma exceção verificada, estenda Exception:
public class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}Para uma exceção não verificada, estenda RuntimeException:
public class InvalidAgeException extends RuntimeException {
public InvalidAgeException(String message) {
super(message);
}
}A chamada super(message) passa a mensagem de erro para a classe pai, tornando-a disponível por meio de getMessage(). Você pode então lançar e capturar sua exceção personalizada como qualquer outra:
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Balance too low: " + balance);
}
balance -= amount;
}
// Usando
try {
account.withdraw(1000);
} catch (InsufficientFundsException e) {
System.out.println(e.getMessage());
}Exceções personalizadas tornam seu código mais legível e permitem que os chamadores lidem com condições de erro específicas de forma diferente. Elas são especialmente valiosas ao construir APIs ou bibliotecas onde a comunicação clara de erros é importante.
Desafio
FácilVamos construir um sistema de reserva de ingressos que utiliza exceções personalizadas para lidar com diferentes cenários de erro! Você criará tipos de exceção significativos que comunicam claramente o que deu errado ao reservar ingressos.
Você organizará seu código em quatro arquivos:
TicketSoldOutException.java: Crie uma exceção verificada (checked exception) personalizada (estendeException) para quando os ingressos não estiverem mais disponíveis. Sua exceção deve aceitar uma mensagem em seu construtor e passá-la para a classe pai usandosuper(message).InvalidSeatException.java: Crie uma exceção não verificada (unchecked exception) personalizada (estendeRuntimeException) para quando alguém tentar reservar um número de assento inválido. Esta exceção também deve aceitar e passar uma mensagem para seu pai.TicketBooth.java: Crie uma classe que gerencie a venda de ingressos. Sua bilheteria deve rastrear o número total de assentos disponíveis e o número de assento válido mais alto. Inclua:Um construtor que recebe o número total de assentos disponíveis.
Um método
bookTicket(int seatNumber)que valida a reserva. Se não restarem ingressos (assentos disponíveis for 0 ou menos), lance umaTicketSoldOutExceptioncom a mensagem"No tickets remaining". Se o número do assento for menor que 1 ou maior que o total de assentos, lance umaInvalidSeatExceptioncom a mensagem"Seat " + seatNumber + " does not exist". Caso contrário, diminua os assentos disponíveis em 1 e imprima"Booked seat " + seatNumber + " successfully".Um método
getAvailableSeats()que retorna a contagem atual de assentos disponíveis.Main.java: Reúna seu sistema de ingressos! Você receberá duas entradas: o número total de assentos e um número de assento para reservar.Crie um
TicketBoothcom o total de assentos fornecido. Em seguida, tente reservar o número do assento especificado dentro de um bloco try-catch. ComoTicketSoldOutExceptioné verificada, você deve tratá-la. CaptureTicketSoldOutExceptionprimeiro e imprima"Booking failed: " + e.getMessage(). Em seguida, captureInvalidSeatExceptione imprima o mesmo formato:"Booking failed: " + e.getMessage().Após o bloco try-catch, imprima
"Remaining seats: " + booth.getAvailableSeats()usando o método getter.
Você receberá duas entradas em ordem: total de assentos (inteiro) e número do assento para reservar (inteiro).
Observe como as exceções verificadas forçam os chamadores a tratá-las (com try-catch ou throws), enquanto as exceções não verificadas não exigem tratamento explícito. Escolha o tipo de exceção com base em se o erro é algo que os chamadores devem antecipar e do qual devem se recuperar!
Folha de consulta
Para criar uma exceção personalizada, estenda uma classe de exceção existente.
Para uma exceção verificada (checked exception), estenda Exception:
public class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}Para uma exceção não verificada (unchecked exception), estenda RuntimeException:
public class InvalidAgeException extends RuntimeException {
public InvalidAgeException(String message) {
super(message);
}
}A chamada super(message) passa a mensagem de erro para a classe pai, tornando-a disponível através de getMessage().
Lance (throw) e capture (catch) exceções personalizadas como qualquer outra exceção:
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Balance too low: " + balance);
}
balance -= amount;
}
// Using it
try {
account.withdraw(1000);
} catch (InsufficientFundsException e) {
System.out.println(e.getMessage());
}Exceções verificadas forçam os chamadores a tratá-las com try-catch ou throws. Exceções não verificadas não exigem tratamento explícito. Escolha com base no fato de o erro ser algo que os chamadores devem antecipar e do qual devem se recuperar.
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int totalSeats = scanner.nextInt();
int seatNumber = scanner.nextInt();
// TODO: Criar um TicketBooth com o total de assentos fornecido
// TODO: Usar um bloco try-catch para tentar reservar o assento
// - Capturar TicketSoldOutException primeiro e imprimir "Booking failed: [exception message]"
// - Capturar InvalidSeatException e imprimir "Booking failed: [exception message]"
// TODO: Após o try-catch, imprimir "Remaining seats: [count]"
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada10Tratamento de Exceções em POO
Hierarquia de Classes de ExceçãoExceções PersonalizadasErros Checked vs UncheckedPadrão Try With ResourcesRecapitulação - Usuário Validado2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Iterator