Exceções encadeadas em Java
1. Visão geral
Neste artigo, daremos uma breve olhada no que éException e nos aprofundaremos na discussão das exceções encadeadas em Java.
Simplificando, umexception é um evento que perturba o fluxo normal de execução do programa. Vamos agora ver exatamente como podemos encadear exceções para obter uma semântica melhor delas.
2. Exceções encadeadas
Exception encadeado ajuda a identificar uma situação em que uma exceção causa outroException em um aplicativo.
For instance, consider a method which throws an ArithmeticException por causa de uma tentativa de divisão por zero, mas a causa real da exceção foi um erro de E / S que fez com que o divisor fosse zero. O método jogaráArithmeticException para o chamador. O chamador não saberia sobre a causa real de umException. Exception encadeado é usado em tais situações.
Este conceito foi introduzido no JDK 1.4.
Vamos ver como as exceções encadeadas são suportadas em Java.
3. ClasseThrowable
A classeThrowable possui alguns construtores e métodos para suportar exceções encadeadas. Em primeiro lugar, vamos dar uma olhada nos construtores.
-
Throwable(Throwable cause)–Throwable tem um único parâmetro, que especifica a causa real de umException.
-
Throwable(String desc, Throwable cause)– este construtor aceita uma descriçãoException com a causa real de umException também.
A seguir, vamos dar uma olhada nos métodos que esta classe oferece:
-
getCause() method - Este método retorna a causa real associada aoException atual.
-
initCause() method - define uma causa subjacente invocandoException.
4. Exemplo
Agora, vamos ver o exemplo em que definiremos nossa própria descrição deException e lançaremos umException encadeado:
public class MyChainedException {
public void main(String[] args) {
try {
throw new ArithmeticException("Top Level Exception.")
.initCause(new IOException("IO cause."));
} catch(ArithmeticException ae) {
System.out.println("Caught : " + ae);
System.out.println("Actual cause: "+ ae.getCause());
}
}
}
Como adivinhado, isso levará a:
Caught: java.lang.ArithmeticException: Top Level Exception.
Actual cause: java.io.IOException: IO cause.
5. Por que exceções encadeadas?
Precisamos encadear as exceções para tornar os logs legíveis. Vamos escrever dois exemplos. Primeiro sem encadear as exceções e segundo, com exceções encadeadas. Posteriormente, compararemos como os logs se comportam nos dois casos.
Para começar, criaremos uma série de exceções:
class NoLeaveGrantedException extends Exception {
public NoLeaveGrantedException(String message, Throwable cause) {
super(message, cause);
}
public NoLeaveGrantedException(String message) {
super(message);
}
}
class TeamLeadUpsetException extends Exception {
// Both Constructors
}
Agora, vamos começar a usar as exceções acima em exemplos de código.
5.1. Sem encadeamento
Vamos escrever um programa de exemplo sem encadear nossas exceções personalizadas.
public class MainClass {
public void main(String[] args) throws Exception {
getLeave();
}
void getLeave() throws NoLeaveGrantedException {
try {
howIsTeamLead();
} catch (TeamLeadUpsetException e) {
e.printStackTrace();
throw new NoLeaveGrantedException("Leave not sanctioned.");
}
}
void howIsTeamLead() throws TeamLeadUpsetException {
throw new TeamLeadUpsetException("Team Lead Upset");
}
}
No exemplo acima, os logs ficarão assim:
com.example.chainedexception.exceptions.TeamLeadUpsetException:
Team lead Upset
at com.example.chainedexception.exceptions.MainClass
.howIsTeamLead(MainClass.java:46)
at com.example.chainedexception.exceptions.MainClass
.getLeave(MainClass.java:34)
at com.example.chainedexception.exceptions.MainClass
.main(MainClass.java:29)
Exception in thread "main" com.example.chainedexception.exceptions.
NoLeaveGrantedException: Leave not sanctioned.
at com.example.chainedexception.exceptions.MainClass
.getLeave(MainClass.java:37)
at com.example.chainedexception.exceptions.MainClass
.main(MainClass.java:29)
5.2. Com encadeamento
A seguir, vamos escrever um exemplo com o encadeamento de nossas exceções personalizadas:
public class MainClass {
public void main(String[] args) throws Exception {
getLeave();
}
public getLeave() throws NoLeaveGrantedException {
try {
howIsTeamLead();
} catch (TeamLeadUpsetException e) {
throw new NoLeaveGrantedException("Leave not sanctioned.", e);
}
}
public void howIsTeamLead() throws TeamLeadUpsetException {
throw new TeamLeadUpsetException("Team lead Upset.");
}
}
Finalmente, vamos dar uma olhada nos registros obtidos com exceções encadeadas:
Exception in thread "main" com.example.chainedexception.exceptions
.NoLeaveGrantedException: Leave not sanctioned.
at com.example.chainedexception.exceptions.MainClass
.getLeave(MainClass.java:36)
at com.example.chainedexception.exceptions.MainClass
.main(MainClass.java:29)
Caused by: com.example.chainedexception.exceptions
.TeamLeadUpsetException: Team lead Upset.
at com.example.chainedexception.exceptions.MainClass
.howIsTeamLead(MainClass.java:44)
at com.example.chainedexception.exceptions.MainClass
.getLeave(MainClass.java:34)
... 1 more
Podemos comparar facilmente os logs mostrados e concluir que as exceções encadeadas levam a logs mais limpos.
6. Conclusão
Neste artigo, vimos o conceito de exceções encadeadas.
A implementação de todos os exemplos pode ser encontrada emthe Github project - este é um projeto baseado em Maven, portanto, deve ser fácil de importar e executar como está.