Связанные исключения в 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, поэтому его должно быть легко импортировать и запускать как есть.