











1. Исключения
Наконец-то программисты додумались регламентировать и автоматизировать обработку ошибок. Произошло это когда изобрели исключения. Сейчас с помощью механизма исключений в мире обрабатывается 80% внештатных ситуаций.
Если исключения придумал какой-нибудь ученый, то скорее всего он защитил на этом докторскую диссертацию. Если же придумал программист, то он, возможно, получил дружеское похлопывание по плечу от коллег: «Вроде норм, бро».
Когда в Java-программе возникает ошибка, например, деление на 0
, происходят такие замечательные вещи:
Шаг первый
Создается специальный объект-исключение, в котором содержится информация о произошедшей ошибке.
Все в Java является объектом, и исключения — не исключение 🙂 Объекты-исключения имеют свои классы, и все их отличие от обычных классов в том, что они унаследованы от класса Throwable
.
Шаг второй
Объект-исключение «выбрасывается». Не сильно удачное название. «Выбрасывание исключения» по своей сути больше похоже на включение пожарной сигнализации или оповещение «боевая тревога».
Когда в систему «выброшено исключение», нормальный режим работы программы прекращается, и начинается «работа по аварийному протоколу».
Шаг третий
Текущий метод, в котором возникло (выброшено) исключение, немедленно завершается. Исключение передается в вызывающий метод, который тоже немедленно завершается. И так по цепочке, пока не завершится метод main
. Вместе с завершением метода main
завершается и программа.
Пример:
Код | Вывод на экран |
---|---|
|
|
В 20-й строке возникла ошибка — деление на 0. Java-машина тут же создала исключение — объект класса ArithmeticException
и «выбросила» его в систему.
Метод поделим()
сразу завершился, поэтому на экран не вывелась строка Ничего страшного не произошло: 0. Программа вернулась в метод конецСвета()
, и ситуация повторилась: в системе есть исключение, а значит, метод конецСвета()
тоже аварийно завершается. Затем завершается метод main
, и выполнение программы прекращается.
А в чем же смысл работы таких исключений? А в том, что в вашей программе можно перехватывать исключения определенного типа и писать свою логику обработки аварийных ситуаций.
2. Перехват исключений try-catch
В Java есть механизм перехвата исключений, который позволяет прекратить аварийное завершение методов. Выглядит он так:
try
{
код, где может возникнуть ошибка
}
catch(ТипИсключения имя)
{
код обработки исключения
}
Эта конструкция называется блок try-catch
.
Код, в котором могут возникнуть исключения, оборачивается в фигурные скобки, перед которыми пишется слово try
(пытаться).
После фигурных скобок пишется ключевое слово catch
, внутри круглых скобок объявляется переменная типа-исключения. Затем следуют фигурные скобки, внутри которых пишется код, который нужно выполнить, если возникло исключение указанного типа.
Если во время выполнения «основного кода» исключений не возникло, код внутри блока catch выполняться не будет. Если же исключение возникло, будет (при условии, что тип возникшего исключения совпадает с типом переменной в круглых скобках).
Пример:
Код | Вывод на экран |
---|---|
|
|
3. Несколько блоков catch
Теоретически внутри блока кода могут возникать самые различные исключения. Некоторые вы захотите обработать одним образом, другие — вторым, третьи вообще решите не обрабатывать.
Разработчики Java решили помочь вам и позволили писать после блока try
не один блок catch
, а несколько.
try
{
код, где может возникнуть ошибка
}
catch(ТипИсключения1 имя1)
{
код обработки исключения1
}
catch(ТипИсключения2 имя2)
{
код обработки исключения2
}
catch(ТипИсключения3 имя3)
{
код обработки исключения3
}
Пример:
Код | Вывод на экран |
---|---|
|
|
4. Порядок блоков catch
Исключение, возникшее в блоке try
, может быть захвачено только одним блоком catch
. Не может быть ситуации, что при обработке исключения выполнился код из нескольких блоков catch
.
Однако порядок блоков имеет значение.
Может быть ситуация, когда исключение захвачено несколькими блоками. В этом случае оно будет захвачено блоком catch, который идет раньше (ближе к блоку try
).
Как же может возникнуть ситуация, что одно исключение могут захватить несколько блоков catch?
Все исключения объединены в единую иерархию с помощью наследования — см. схему.
Объект-исключение типа ArithmeticException
может быть присвоен переменной типа ArithmeticException
, а также переменным его классов-предков: RuntimeException
, Exception
и Throwable
— см. схему.
Подробнее о наследовании и классах-предках мы поговорим на 21 уровне.
Вот этот код будет отлично компилироваться:
Преимущества наследования: |
---|
|
Поэтому и перехватить исключение типа ArithmeticException
можно блоками catch
любым из 4-х приведенных выше типов.
Пример 1:
Код | Вывод на экран |
---|---|
|
|
В данном примере исключение ArithmeticException
может быть перехвачено и блоком catch(Exception e)
, и блоком catch(ArithmeticException e)
. Оно будет захвачено тем блоком, который идет ближе к блоку try
— первым блоком catch
.
Чтобы не было неожиданностей, лучше всего блоки catch
, которые могут захватить почти все исключения, размещать ближе к концу списка блоков catch
.
Тип Throwable
вообще способен перехватывать все возможные исключения в Java, если его разместить в первом блоке catch
- код не скомпилируется, так как компилятор понимает, что в коде есть недосягаемые блоки кода.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ