Верижни изключения в Java

1. Общ преглед

В тази статия ще разгледаме накратко какво е изключение и ще разгледаме задълбочено обсъждането на оковите изключения в Java.

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

2. Верижни изключения

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

Например, помислете за метод, който хвърля ArithmeticException поради опит за разделяне на нула, но действителната причина за изключение е грешка при входа / изхода, която е причинила делителят да е нула. Методът ще хвърли ArithmeticException на повикващия. Повикващият не би знаел за действителната причина за изключение . В такива ситуации се използва Chained Exception .

Тази концепция е въведена в JDK 1.4.

Нека да видим как в Java се поддържат верижни изключения.

3. Клас за хвърляне

Класът Throwable има някои конструктори и методи за поддържане на верижни изключения. Първо, нека разгледаме конструкторите.

  • Throwable (Throwable причина) - Throwable има един параметър, който определя действителната причина за изключение .
  • Throwable (String desc, Throwable причина) - този конструктор приема иописаниена изключение с действителната причина за изключение .

След това нека да разгледаме методите, които този клас предоставя:

  • метод getCause () - Този метод връща действителната причина, свързана с текущото изключение .
  • initCause () метод - Той задава основна причина с извикване на изключение .

4. Пример

Сега, нека разгледаме примера, в който ще зададем наше собствено описание на изключението и ще хвърлим верижно изключение :

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.baeldung.chainedexception.exceptions.TeamLeadUpsetException: Team lead Upset at com.baeldung.chainedexception.exceptions.MainClass .howIsTeamLead(MainClass.java:46) at com.baeldung.chainedexception.exceptions.MainClass .getLeave(MainClass.java:34) at com.baeldung.chainedexception.exceptions.MainClass .main(MainClass.java:29) Exception in thread "main" com.baeldung.chainedexception.exceptions. NoLeaveGrantedException: Leave not sanctioned. at com.baeldung.chainedexception.exceptions.MainClass .getLeave(MainClass.java:37) at com.baeldung.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.baeldung.chainedexception.exceptions .NoLeaveGrantedException: Leave not sanctioned. at com.baeldung.chainedexception.exceptions.MainClass .getLeave(MainClass.java:36) at com.baeldung.chainedexception.exceptions.MainClass .main(MainClass.java:29) Caused by: com.baeldung.chainedexception.exceptions .TeamLeadUpsetException: Team lead Upset. at com.baeldung.chainedexception.exceptions.MainClass .howIsTeamLead(MainClass.java:44) at com.baeldung.chainedexception.exceptions.MainClass .getLeave(MainClass.java:34) ... 1 more

Можем лесно да сравним показаните регистрационни файлове и да заключим, че верижните изключения водят до по-чисти регистрационни файлове.

В тази статия разгледахме концепцията за верижни изключения.

Изпълнението на всички примери може да бъде намерено в проекта Github - това е проект, базиран на Maven, така че трябва да е лесно да се импортира и да се изпълнява както е.