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, така че трябва да е лесно да се импортира и да се изпълнява както е.