Обработка исключений

В процессе работы программы могут случаться различные непредвиденные проблемы.
Например:
- При скачивании файла оборвалось соединение...
-- Такое вполне может произойти, например если у пользователя плохой сигнал wi-fi.
- При попытке записать файл на USB устройство и устройство оказалось недоступно...
-- Такое может случиться, если пользователь задел рукой USB устройство.
- При попытке выполнить запрос к базе данных, может оказаться, что она недоступна.
-- Такое может случиться, если сервер с БД выключился/перезагрузился и т.п.
Примеров можно приводить много. Любая из этих проблем, потенциально может вывести из строя вашу программу.

Ошибки в работе программы - это конечно плохо, и к сожалению они случаются. Было бы неплохо их максимально предсказывать и если они случаются, то лучше постараться быть вкурсе и держать ситуацию под контролем.

Хорошие новости

В java есть механизм обработки ошибок исключений!

Помимо того, что такой механизм существует, java вообще в некоторых случаях не скомпилируется, если вы не будете контролировать потенциально опасные места программы.

Попробуйте например запустить пример показанный ниже пример.

В файле Main.java

import java.net.Socket; public class Client { public static void main(String[] args) { Socket socket = new Socket("127.0.0.1", 9123); } }

Ну и какой итог?
java: unreported exception java.net.UnknownHostException; must be caught or declared to be thrown

Java сообщает нам, что мы должны были перехватить исключение. Без этого, программа отказывается собираться.
- А зачем здесь это? Какие могут быть проблемы?
-- В данном примере, мы подключаемся к серверу, но может случиться ситуация, что сервер недоступен, и вот что тогда делать???
Вот как раз для того, чтобы java знала, что нужно делать в этой ситуации, мы должны обрабатывать исключения!

Определение: Исключения представляют собой события, которые возникают во время выполнения программы и могут привести к нарушению нормального потока выполнения.


Использование блоков try-catch

Блок try используется для обозначения участка кода, в котором может произойти исключение, а блок catch - для обработки возникшего исключения.

  try - пытаться
  catch - ловить
  finally - в конце концов
public class Main { public static void main(String[] args) { try { // возможно вызывающий исключение код } catch (Exception e) { // обработка исключения }finally{ // код исполняющийся независимо от того, возникло ли исключение в блоке try или нет } } }

Отлично, как это выглядит синтаксически понятно, теперь давайте допустим ошибку.

public class Main { public static void main(String[] args) { int[] nums = {4,2,1}; System.out.println(nums[0]); System.out.println(nums[1]); System.out.println(nums[2]); System.out.println(nums[3]); // Внимание на эту строку, инекса [3] не существует!!! System.out.println("Program end"); // Эта строка не выполнится } }
Результат:

4
2
1
Exception in thread "main" java.lang. ArrayIndexOutOfBoundsException : Index 3 out of bounds for length 3 at Main5.main(Main.java:7)
Process finished with exit code 1

Как видно из примера, программа споткнулась на 7 строчке, из-за обращения к несуществующему индексу.

Попробуем записать код в блок try-catch

public class Main { public static void main(String[] args) { try { int[] nums = {4,2,1}; System.out.println(nums[0]); System.out.println(nums[1]); System.out.println(nums[2]); System.out.println(nums[3]); }catch (Exception e){ e.printStackTrace(); // Вывод информации об исключении } System.out.println("Program end"); } }
Результат:

4
2
1
Program end
Exception in thread "main" java.lang. ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 at Main5.main(Main.java:7)
Process finished with exit code 0

Отлично! Теперь вся программа корректно отработала и завершилась с code 0. Строка e.printStackTrace(); позволила нам увидеть, что случилось в процессе исполнения алгоритма, но обращение к элементу nums[3], не приводит к ошибке в программе.


Внимательный читатель заметит, что программа с массивом int[] nums = {4,2,1}; без try-catch всё-таки скомпилировалась и запустилась.
В примере со строкой Socket socket = new Socket("127.0.0.1", 9123); программа выдала ошибку на мементе компиляции.
В чём же разница, как это вообще работает?
Давайте разбираться...

В языке Java существует два типа исключений checked и unchecked.
Checked exception - это исключения, которые обязательно должны быть обработаны в коде или объявлены в сигнатуре метода с помощью ключевого слова throws. Компилятор Java требует обработки checked исключений для того, чтобы предотвратить возможные ошибки времени выполнения.
- По логике вещей, такого рода ситуации (ошибки) можно предвидеть.
Unchecked exception - это исключения, которые не требуют явного обработчика или объявления с помощью ключевого слова throws. Unchecked исключения наследуются от класса RuntimeException или его подклассов. В отличие от checked исключений, компилятор Java не требует обработки unchecked исключений

Иерархическая структура наследования классов

Обсудим логику создателей языка Java.
Error - это ошибки которые невозможно проконтроллировать на момент компиляции. Например StackOverflow (переполнение стека), может возникнуть когда метод вызвал сам себя (рекурсивно) большое колличество раз. Это серъёзная проблема, никакой try-catch тут не поможет!
RuntimeException - это исключения которые возникают во время выполнения программы, отсюда и название Run Time. Как и с Error, компилятор не может предсказать их заранее, но в отличие от Error их можно обработать, если конечно вы понимаете, что, что-то может пойти не так.
И вот как раз в примере с массивом int[] nums = {4,2,1}; мы имеели дело с RuntimeException, поэтому программа скомпилировалась.
IOException - это исключения ввода-вывода IO - Input-Output. Вполне очевидно, что при попытке записать что-то куда-то или прочитать откуда-то может возникнуть проблема.
Так давайте обяжем разработчиков в обязательном порядке обрабатывать эти исключения - подумали создатели java. И поэтому, когда мы пытались запустить программу со строкой Socket socket = new Socket("127.0.0.1", 9123);, программа выдала ошибку на мементе компиляции.


Мы рассмотрели понятие обработки исключений и использование блоков try-catch для обеспечения надежности программного кода. Правильная обработка исключений позволяет предотвратить аварийное завершение программы и уведомить пользователя о возникших проблемах.
Не забывайте подкреплять теорию практикой и дивгайтесь дальше!


Комментарии

Добавить комментарий

Чтобы оставить комменатрий необходимо Авторизоваться