Exceções encadeadas em Java

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á.