Desafio Java

Sistema bancário com múltiplas exceções e finally

Enunciado

Implemente um sistema bancário simples com operações de depósito e saque. Crie duas exceções personalizadas: SaldoInsuficienteException (checked) e ValorInvalidoException (unchecked). O método sacar deve lançar SaldoInsuficienteException se o valor for maior que o saldo, e ValorInvalidoException se o valor for negativo ou zero. O método depositar deve lançar ValorInvalidoException para valores não positivos. No main, realize uma sequência de operações e use try/catch/finally para tratar erros e exibir o saldo final.

Requisitos

  • SaldoInsuficienteException deve ser checked e ValorInvalidoException unchecked.
  • O método sacar deve lançar as duas exceções conforme as condições.
  • O método depositar deve lançar ValorInvalidoException para valores <= 0.
  • O bloco finally deve exibir o saldo final após cada operação.

Código inicial

// Defina as exceções personalizadas aqui

public class Banco {
    private double saldo;

    public Banco(double saldoInicial) {
        this.saldo = saldoInicial;
    }

    public void sacar(double valor) /* throws ... */ {
        // TODO: valide e lance exceções
    }

    public void depositar(double valor) {
        // TODO: valide e lance exceção
    }

    public double getSaldo() {
        return saldo;
    }

    public static void main(String[] args) {
        Banco conta = new Banco(100.0);
        // TODO: realize operações e trate exceções
    }
}

Saída esperada

Depósito de 50.0 realizado. Saldo: 150.0
Saque de 200.0 falhou: Saldo insuficiente
Saque de -10.0 falhou: Valor inválido
Depósito de -5.0 falhou: Valor inválido
Saldo final: 150.0
Ver dica

No main, chame os métodos dentro de blocos try separados. Use finally para imprimir o saldo após cada operação. Lembre-se de que ValorInvalidoException é unchecked, então não precisa declarar throws para ela.

Mostrar solução
class SaldoInsuficienteException extends Exception {
    public SaldoInsuficienteException(String mensagem) {
        super(mensagem);
    }
}

class ValorInvalidoException extends RuntimeException {
    public ValorInvalidoException(String mensagem) {
        super(mensagem);
    }
}

public class Banco {
    private double saldo;

    public Banco(double saldoInicial) {
        this.saldo = saldoInicial;
    }

    public void sacar(double valor) throws SaldoInsuficienteException {
        if (valor <= 0) {
            throw new ValorInvalidoException("Valor inválido");
        }
        if (valor > saldo) {
            throw new SaldoInsuficienteException("Saldo insuficiente");
        }
        saldo -= valor;
    }

    public void depositar(double valor) {
        if (valor <= 0) {
            throw new ValorInvalidoException("Valor inválido");
        }
        saldo += valor;
    }

    public double getSaldo() {
        return saldo;
    }

    public static void main(String[] args) {
        Banco conta = new Banco(100.0);

        try {
            conta.depositar(50.0);
            System.out.println("Depósito de 50.0 realizado. Saldo: " + conta.getSaldo());
        } catch (ValorInvalidoException e) {
            System.out.println("Depósito falhou: " + e.getMessage());
        } finally {
            System.out.println("Saldo atual: " + conta.getSaldo());
        }

        try {
            conta.sacar(200.0);
            System.out.println("Saque de 200.0 realizado. Saldo: " + conta.getSaldo());
        } catch (SaldoInsuficienteException e) {
            System.out.println("Saque de 200.0 falhou: " + e.getMessage());
        } catch (ValorInvalidoException e) {
            System.out.println("Saque de 200.0 falhou: " + e.getMessage());
        } finally {
            System.out.println("Saldo atual: " + conta.getSaldo());
        }

        try {
            conta.sacar(-10.0);
            System.out.println("Saque de -10.0 realizado. Saldo: " + conta.getSaldo());
        } catch (SaldoInsuficienteException e) {
            System.out.println("Saque de -10.0 falhou: " + e.getMessage());
        } catch (ValorInvalidoException e) {
            System.out.println("Saque de -10.0 falhou: " + e.getMessage());
        } finally {
            System.out.println("Saldo atual: " + conta.getSaldo());
        }

        try {
            conta.depositar(-5.0);
            System.out.println("Depósito de -5.0 realizado. Saldo: " + conta.getSaldo());
        } catch (ValorInvalidoException e) {
            System.out.println("Depósito de -5.0 falhou: " + e.getMessage());
        } finally {
            System.out.println("Saldo atual: " + conta.getSaldo());
        }

        System.out.println("Saldo final: " + conta.getSaldo());
    }
}

Passo a passo

  1. Definimos SaldoInsuficienteException como checked (estende Exception).
  2. Definimos ValorInvalidoException como unchecked (estende RuntimeException).
  3. A classe Banco tem um atributo saldo e métodos sacar, depositar e getSaldo.
  4. No sacar, verificamos se o valor é <= 0 e lançamos ValorInvalidoException (unchecked).
  5. Se o valor for maior que o saldo, lançamos SaldoInsuficienteException (checked).
  6. No depositar, apenas verificamos valor <= 0 e lançamos ValorInvalidoException.
  7. No main, realizamos quatro operações, cada uma em um bloco try/catch/finally.
  8. O finally imprime o saldo atual após cada tentativa, independentemente de erro.

Por que funciona

O uso combinado de exceções checked e unchecked permite diferenciar erros recuperáveis (saldo insuficiente) de erros de programação (valor inválido). O finally garante que o saldo seja sempre exibido, mantendo o usuário informado. A captura específica de cada exceção permite mensagens de erro precisas.

Erros comuns

  • Não declarar throws SaldoInsuficienteException no método sacar: erro de compilação, pois é checked.
  • Lançar ValorInvalidoException sem capturar: como é unchecked, o programa compila, mas se não for capturada, a exceção sobe e pode encerrar o programa.
  • Esquecer o finally: o saldo não seria exibido após cada operação, contrariando o requisito.
  • Ordem errada dos catch: capturar Exception antes de SaldoInsuficienteException causaria erro de compilação (exceção já capturada).

Outra forma de resolver

Você pode usar um único bloco try com múltiplos catch para todas as operações, mas isso dificultaria identificar qual operação falhou. A abordagem separada é mais clara.

Saída esperada

Depósito de 50.0 realizado. Saldo: 150.0
Saldo atual: 150.0
Saque de 200.0 falhou: Saldo insuficiente
Saldo atual: 150.0
Saque de -10.0 falhou: Valor inválido
Saldo atual: 150.0
Depósito de -5.0 falhou: Valor inválido
Saldo atual: 150.0
Saldo final: 150.0