Menu
Coddy logo textTech

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.

challenge icon

Desafio

Fácil

Vamos 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 (estende Exception) 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 usando super(message).
  • InvalidSeatException.java: Crie uma exceção não verificada (unchecked exception) personalizada (estende RuntimeException) 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 uma TicketSoldOutException com a mensagem "No tickets remaining". Se o número do assento for menor que 1 ou maior que o total de assentos, lance uma InvalidSeatException com 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 TicketBooth com o total de assentos fornecido. Em seguida, tente reservar o número do assento especificado dentro de um bloco try-catch. Como TicketSoldOutException é verificada, você deve tratá-la. Capture TicketSoldOutException primeiro e imprima "Booking failed: " + e.getMessage(). Em seguida, capture InvalidSeatException e 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]"
    }
}
quiz iconTeste seus conhecimentos

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