1. Видове изключения

Всички изключения са разделени на 4 типа, които всъщност са класове, които се наследяват един друг.
Throwable
клас
Базовият клас за всички изключения е класът Throwable
. Класът Throwable
съдържа codeа, който записва текущия стек за извикване (проследяване на стека на текущия метод) в масив. Ще научим Howво е проследяване на стека малко по-късно.
Операторът за хвърляне може да приеме само обект, който произлиза от Throwable
класа. И въпреки че теоретично можете да напишете code като throw new Throwable();
, обикновено никой не прави това. Основната цел на Throwable
класа е да има един родителски клас за всички изключения.
Error
клас
Следващият клас изключение е Error
класът, който директно наследява Throwable
класа. Java машината създава обекти от Error
класа (и неговите наследници), когато възникнат сериозни проблеми . Например хардуерна неизправност, недостатъчна памет и др.
Обикновено, като програмист, не можете да направите нищо в ситуация, в която такава грешка (видът, за който Error
трябва да бъде хвърлен) е възникнала в програмата: тези грешки са твърде сериозни. Всичко, което можете да направите, е да уведомите потребителя, че програмата се срива и/or да запишете цялата известна информация за грешката в регистрационния файл на програмата.
Exception
клас
Класовете Exception
и RuntimeException
са за често срещани грешки, които се случват при работата на много методи. Целта на всяко хвърлено изключение е да бъде уловено от catch
блок, който знае How правилно да се справи с него.
Когато даден метод не може да завърши работата си по няHowва причина, той трябва незабавно да уведоми извикващия метод, като хвърли изключение от съответния тип.
С други думи, ако една променлива е равна на null
, методът ще хвърли NullPointerException
. Ако неправилните аргументи са бor предадени на метода, той ще изведе InvalidArgumentException
. Ако методът случайно раздели на нула, той ще хвърли ArithmeticException
.
RuntimeException
клас
RuntimeExceptions
са подмножество на Exceptions
. Можем дори да кажем, че това RuntimeException
е олекотена version на обикновените изключения ( Exception
) — на такива изключения се налагат по-малко изисквания и ограничения
Ще научите разликата между Exception
и RuntimeException
по-късно.
2. Throws
: проверени изключения

Всички изключения на Java попадат в 2 категории: проверени и непроверени .
Всички изключения, които наследяват RuntimeException
or Error
се считат за непроверени изключения . Всички останали са проверени изключения .
Двадесет години след като бяха въведени проверените изключения, почти всеки Java програмист смята това за грешка. В популярните съвременни рамки 95% от всички изключения не са отметнати. Езикът C#, който почти точно копира Java, не добави проверени изключения .
Каква е основната разлика между проверените и непроверените изключения?
Има допълнителни изисквания, наложени на проверените изключения. Грубо казано, те са следните:
Изискване 1
Ако даден метод хвърля проверено изключение , той трябва да посочи типа изключение в своя подпис . По този начин всеки метод, който го извиква, е наясно, че това "смислено изключение" може да възникне в него.
Посочете проверените изключения след параметрите на метода след throws
ключовата дума (не използвайте throw
ключовата дума по погрешка). Изглежда нещо подобно:
type method (parameters) throws exception
Пример:
проверено изключение | непроверено изключение |
---|---|
|
|
В примера вдясно, нашият code хвърля непроверено изключение — не са необходими допълнителни действия. В примера отляво методът хвърля проверено изключение, така че throws
ключовата дума се добавя към подписа на метода заедно с типа на изключението.
Ако даден метод очаква да хвърли множество проверени изключения, всички те трябва да бъдат посочени след throws
ключовата дума, разделени със запетаи. Редът не е важен. Пример:
public void calculate(int n) throws Exception, IOException
{
if (n == 0)
throw new Exception("n is null!");
if (n == 1)
throw new IOException("n is 1");
}
Изискване 2
Ако извикате метод, който е проверил изключения в сигнатурата си, не можете да пренебрегнете факта, че той ги хвърля.
Трябва or да уловите всички такива изключения, като добавите catch
блокове за всяко от тях, or като ги добавите към throws
клауза за вашия метод.
Сякаш казваме: „ Тези изключения са толкова важни, че трябва да ги уловим. И ако не знаем How да се справим с тях, тогава всеки, който може да извика нашия метод, трябва да бъде уведомен, че такива изключения могат да възникнат в него.
Пример:
Представете си, че пишем метод за създаване на свят, населен с хора. Първоначалният брой хора се предава като аргумент. Така че трябва да добавим изключения, ако има твърде малко хора.
Създаване на Земята | Забележка |
---|---|
|
Методът потенциално хвърля две проверени изключения:
|
Това извикване на метод може да се обработва по 3 начина:
1. Не хващайте ниHowви изключения
Това най-често се прави, когато методът не знае How правилно да се справи със ситуацията.
Код | Забележка |
---|---|
|
Извикващият метод не улавя изключенията и трябва да информира другите за тях: той ги добавя към собствената си throws клауза |
2. Хванете някои от изключенията
Ние се справяме с грешките, с които можем да се справим. Но тези, които не разбираме, ги хвърляме към извикващия метод. За да направим това, трябва да добавим името им към клаузата throws:
Код | Забележка |
---|---|
|
Обаждащият се улавя само едно проверено изключение — LonelyWorldException . Другото изключение трябва да се добави към сигнатурата му, като се посочи след throws ключовата дума |
3. Уловете всички изключения
Ако методът не хвърля изключения към извикващия метод, тогава извикващият метод винаги е уверен, че всичко е работило добре. И няма да може да предприеме ниHowви действия за коригиране на извънредни ситуации.
Код | Забележка |
---|---|
|
Всички изключения се улавят в този метод. Обаждащият се ще бъде уверен, че всичко е минало добре. |
3. Прихващане на множество изключения
Програмистите наистина мразят да дублират code. Те дори излязоха със съответния принцип на развитие — DRY : Don't Repeat Yourself. Но когато се обработват изключения, има чести случаи, когато един try
блок е последван от няколко catch
блока със същия code.
Или може да има 3 catch
блока със същия code и още 2 catch
блока с друг идентичен code. Това е стандартна ситуация, когато вашият проект обработва изключенията отговорно.
Започвайки с version 7, в езика Java е добавена възможността за указване на множество типове изключения в един catch
блок. Изглежда приблизително така:
try
{
// Code where an exception might occur
}
catch (ExceptionType1 | ExceptionType2 | ExceptionType3 name)
{
// Exception handling code
}
Можете да имате толкова catch
блокове, колкото искате. Един catch
блок обаче не може да указва изключения, които се наследяват едно друго. С други думи, не можете да напишете catch ( Exception
| RuntimeException
e), защото RuntimeException
класът наследява Exception
.
GO TO FULL VERSION