Trilhas
/
Java
Java
/
Exercícios
/
O enigma da calculadora
O enigma da calculadora

O enigma da calculadora

Exercício de aprendizagem

Introdução

Exceções

A linguagem de programação Java usa exceções para lidar com erros e outros eventos excepcionais.

O que é uma exceção

Uma exceção é um evento que ocorre durante a execução de um programa e que interrompe o fluxo normal das instruções. Em Java, as exceções são geradas explicitamente, e o ato de gerar uma exceção é chamado de lançar uma exceção. O ato de tratar uma exceção é chamado de capturar uma exceção.

Em Java, todas as exceções são subclasses da classe Exception, que por sua vez é uma subclasse de Throwable.

Java distingue dois tipos de exceções:

  1. Exceções verificadas
  2. Exceções não verificadas
Exceções verificadas

Exceções verificadas são condições excepcionais que uma aplicação deve prever e das quais deve se recuperar. Um exemplo de exceção verificada é a FileNotFoundException, que ocorre quando um método tenta ler um arquivo que não existe.

Esse tipo de exceção é verificado em tempo de compilação: métodos que lançam exceções verificadas devem declarar isso na assinatura do método, e o código que chama um método que pode lançar uma exceção verificada precisa tratá-la, ou o código não compila.

Todas as exceções verificadas são subclasses de Exception que não estendem RuntimeException.

Exceções não verificadas

Exceções não verificadas são condições excepcionais que uma aplicação geralmente não consegue prever nem das quais consegue se recuperar. Um exemplo de exceção não verificada é a NullPointerException, que ocorre quando um método espera um valor não nulo, mas recebe null.

Esse tipo de exceção não é verificado em tempo de compilação: métodos que lançam exceções não verificadas não precisam declarar isso na assinatura do método, e o código que chama um método que pode lançar uma exceção não verificada não precisa tratá-la.

Todas as exceções não verificadas herdam de RuntimeException, que por sua vez é uma extensão de Exception.

Lançando exceções

Um método em Java pode lançar uma exceção usando a instrução throw.

Lançando uma exceção verificada

Ao lançar uma exceção verificada de um método, é preciso declarar isso na assinatura do método usando a palavra-chave throws, como mostra o exemplo abaixo. Isso obriga o código que faz a chamada a prever que uma exceção pode ser lançada e a tratá-la adequadamente.

public class InsufficientBalanceException extends Exception {

}

public class BankAccount {
  public void withdraw(double amount) throws InsufficientBalanceException {
    if (balance < amount) {
      throw new InsufficientBalanceException();
    }

    // rest of the method implementation
  }
}
Lançando uma exceção não verificada

Ao lançar uma exceção não verificada de um método, não é preciso declarar isso na assinatura do método, embora isso seja permitido.

public class BankAccount {
  public void withdraw(double amount) {
    if (amount < 0) {
      throw new IllegalArgumentException("Cannot withdraw a negative amount");
    }

    // rest of the method implementation
  }
}

Tratando exceções

O tratamento de exceções em Java é feito com as palavras-chave try, catch e finally.

  • As instruções de código que podem lançar uma exceção devem ser envolvidas em um bloco try.
  • O bloco try é seguido por um ou mais blocos catch, que capturam as exceções lançadas no bloco try.
  • Os blocos catch podem ser seguidos, opcionalmente, por um bloco finally, que sempre é executado depois do bloco try, independentemente de uma exceção ter sido lançada ou não.

O exemplo a seguir mostra como essas palavras-chave funcionam:

public class ATM {
  public void withdraw(BankAccount bankAccount, double amount) {
    try {
      System.out.println("Withdrawing " + amount);
      bankAccount.withdraw(amount);
      System.out.println("Withdrawal succeeded");
    } catch (InsufficientBalanceException) {
      System.out.println("Withdrawal failed: insufficient balance");
    } catch (RuntimeException e) {
      System.out.println("Withdrawal failed: " + e.getMessage());
    } finally {
      System.out.println("Current balance: " + bankAccount.getBalance());
    }
  }
}

Neste exemplo, quando nenhuma exceção é lançada, o seguinte é impresso:

Withdrawing 10.0
Withdrawal succeeded
Current balance: 5.0

No entanto, se a instrução bankAccount.withdraw(amount) lançar uma InsufficientBalanceException, o seguinte é impresso:

Withdrawing 10.0
Withdrawal failed: insufficient balance
Current balance: 5.0

Ou, caso uma exceção não verificada seja lançada por bankAccount.withdraw(amount), o seguinte é impresso:

Withdrawing -10.0
Withdrawal failed: Cannot withdraw a negative amount
Current balance: 5.0

Erros

Java também tem uma categoria separada chamada Erros, que são problemas graves e externos à aplicação. Um exemplo de erro é o OutOfMemoryError, que ocorre quando uma aplicação tenta usar mais memória do que a disponível no sistema.

Assim como as exceções não verificadas, os erros não são verificados em tempo de compilação. A diferença é que eles representam problemas de nível de sistema e geralmente são lançados pela máquina virtual Java ou pelo ambiente, e não pela aplicação. Em geral, as aplicações não devem tentar capturá-los nem tratá-los.

Todos os erros em Java herdam da classe Error.

Instruções

Neste exercício você vai implementar o tratamento de erros de uma calculadora simples de números inteiros. Para simplificar, os métodos para calcular adição, multiplicação e divisão já são fornecidos.

O objetivo é ter uma calculadora que funcione e que retorne uma String com o seguinte padrão: 16 + 51 = 67, quando ela receber os argumentos 16, 51 e +.

CalculatorConundrum calculator = new CalculatorConundrum();

calculator.calculate(16, 51, "+");
// => returns "16 + 51 = 67"

calculator.calculate(32, 6, "*");
// => returns "32 * 6 = 192"

calculator.calculate(512, 4, "/");
// => returns "512 / 4 = 128"

1. Implemente o método calculate para dar suporte a algumas operações básicas

O método principal a ser implementado nesta tarefa será o método CalculatorConundrum.calculate(). Ele recebe três argumentos. Os dois primeiros argumentos, operand1 e operand2, são números inteiros sobre os quais uma operação vai atuar. O terceiro argumento, operation, é do tipo String e, para este exercício, é necessário implementar as seguintes operações:

  • adição usando a String +
  • multiplicação usando a String *
  • divisão usando a String /

2. Trate operações ilegais

Atualize o método CalculatorConundrum.calculate() para tratar operações ilegais:

  • Quando o argumento operation for null, deve ser lançada uma IllegalArgumentException com a mensagem Operation cannot be null.
  • Quando o argumento operation for "", deve ser lançada uma IllegalArgumentException com a mensagem Operation cannot be empty.
  • Quando o argumento operation for qualquer operação diferente de +, * ou /, deve ser lançada uma IllegalOperationException com a mensagem Operation '{operation}' does not exist.
calculator.calculate(10, 1, null);
// => throws IllegalArgumentException with message "Operation cannot be null"

calculator.calculate(10, 1, "");
// => throws IllegalArgumentException with message "Operation cannot be empty"

calculator.calculate(10, 1, "-");
// => throws IllegalOperationException with message "Operation '-' does not exist"

3. Trate a exceção lançada ao dividir por zero

Em Java, tentar dividir por zero lança uma ArithmeticException. Atualize o método CalculatorConundrum.calculate() para capturar essa exceção e, em seguida, lançar uma IllegalOperationException com a mensagem Division by zero is not allowed e a ArithmeticException capturada como sua causa.

calculator.calculate(512, 0, "/");
// => throws IllegalOperationException with message "Division by zero is not allowed"
Editar via GitHub O link abre em uma nova janela ou aba
Java Exercism

Tudo pronto para começar O enigma da calculadora?

Crie sua conta no Exercism para aprender e dominar Java com 26 conceitos158 exercícios e mentoria humana de verdade, tudo de graça.