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 através 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 sua classe 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 do 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 é 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 imprimaBooked 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 imprimaBooking failed: [exception message]. Em seguida, captureInvalidSeatExceptione imprima o mesmo formato:Booking failed: [exception message].Após o bloco try-catch, imprima
Remaining seats: [count]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 obrigam 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 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: Crie um TicketBooth com o total de assentos fornecido
// TODO: Use um bloco try-catch para tentar reservar o assento
// - Capture TicketSoldOutException primeiro e imprima "Booking failed: [exception message]"
// - Capture InvalidSeatException e imprima "Booking failed: [exception message]"
// TODO: Após o try-catch, imprima "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