A linguagem de programação Java usa exceções para lidar com erros e outros eventos excepcionais.
Uma exceção é um evento que ocorre durante a execução de um programa e que interrompe o fluxo normal das instruções. As exceções são lançadas explicitamente em Java, e o ato de lançar 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.
O Java distingue dois tipos de exceções:
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 especificar 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 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 especificar 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.
Um método em Java pode lançar uma exceção usando a instrução throw.
Ao lançar uma exceção verificada de um método, é preciso especificar isso na assinatura do método usando a palavra-chave throws, como mostra o exemplo abaixo.
Isso força 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
}
}
Ao lançar uma exceção não verificada de um método, não é preciso especificar isso na assinatura do método, embora isso seja possível.
public class BankAccount {
public void withdraw(double amount) {
if (amount < 0) {
throw new IllegalArgumentException("Cannot withdraw a negative amount");
}
// rest of the method implementation
}
}
O tratamento de exceções em Java é feito com as palavras-chave try, catch e finally.
try.try é seguido por um ou mais blocos catch, que capturam as exceções lançadas no bloco try.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());
}
}
}
Nesse exemplo, quando nenhuma exceção é lançada, o seguinte é impresso:
Withdrawing 10.0
Withdrawal succeeded
Current balance: 5.0
No entanto, caso a instrução bankAccount.withdraw(amount) lance 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
O Java também tem uma categoria separada chamada Erros, que são problemas graves 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 capturar nem tratar esses erros.
Todos os erros em Java herdam da classe Error.
Como dito anteriormente, as exceções são eventos que interrompem o fluxo normal das instruções e são usadas para tratar eventos excepcionais. Por isso, não é recomendado usar exceções para controlar o fluxo da sua aplicação.