Связанные исключения в Java

Связанные исключения в Java

 

1. обзор

В этой статье мы очень кратко рассмотрим, что такоеException, и подробно рассмотрим связанные исключения в Java.

Проще говоря,exception - это событие, которое нарушает нормальный ход выполнения программы. Давайте теперь посмотрим, как мы можем связать исключения, чтобы получить от них лучшую семантику.

2. Связанные исключения

СвязанныйException помогает идентифицировать ситуацию, в которой одно исключение вызывает другоеException в приложении.

For instance, consider a method which throws an ArithmeticException из-за попытки деления на ноль, но фактической причиной исключения была ошибка ввода-вывода, из-за которой делитель был равен нулю. Метод выбрасываетArithmeticException вызывающей стороне. Вызывающий не может знать о фактической причинеException. В таких ситуациях используется цепочкаException.

Эта концепция была введена в JDK 1.4.

Давайте посмотрим, как в Java поддерживаются связанные исключения.

3. Throwable Класс

В классеThrowable есть конструкторы и методы для поддержки связанных исключений. Во-первых, давайте посмотрим на конструкторы.

  • Throwable(Throwable cause)Throwable имеет единственный параметр, который указывает действительную причинуException.

  • Throwable(String desc, Throwable cause) этот конструктор также принимает описаниеException с фактической причинойException.

Затем давайте посмотрим на методы, которые предоставляет этот класс:

  • getCause() method - этот метод возвращает фактическую причину, связанную с текущимException.

  • initCause() method - устанавливает основную причину при вызовеException.

4. пример

Теперь давайте посмотрим на пример, в котором мы зададим собственное описаниеException и создадим цепочкуException:

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());
        }
    }
}

Как и предполагалось, это приведет к:

Caught: java.lang.ArithmeticException: Top Level Exception.
Actual cause: java.io.IOException: IO cause.

5. Почему цепные исключения?

Нам нужно объединить исключения, чтобы сделать журналы читабельными. Напишем два примера. Во-первых, без цепочек исключений, а во-вторых, с цепочками исключений. Позже мы сравним, как ведут себя логи в обоих случаях.

Для начала мы создадим серию исключений:

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
}

Теперь давайте начнем использовать указанные выше исключения в примерах кода.

5.1. Без цепочки

Давайте напишем пример программы без цепочки наших пользовательских исключений.

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");
    }
}

В приведенном выше примере журналы будут выглядеть так:

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. С цепочкой

Затем давайте напишем пример с цепочкой наших пользовательских исключений:

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.");
    }
}

Наконец, давайте посмотрим на журналы, полученные с цепочкой исключений:

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

Мы можем легко сравнить показанные журналы и сделать вывод, что связанные исключения приводят к более чистым журналам.

6. Заключение

В этой статье мы рассмотрели концепцию связанных исключений.

Реализации всех примеров можно найти вthe Github project - это проект на основе Maven, поэтому его должно быть легко импортировать и запускать как есть.