1. Вступ
У цьому підручнику ми розглянемо, як створити власний виняток у Java .
Ми покажемо, як визначені користувачем винятки реалізуються та використовуються як для перевірених, так і для неперевірених винятків.
2. Необхідність спеціальних винятків
Винятки Java охоплюють майже всі загальні винятки, які неодмінно трапляються в програмуванні.
Однак іноді нам потрібно доповнити ці стандартні винятки власними.
Основними причинами запровадження спеціальних винятків є:
- Винятки з бізнес-логіки - винятки, характерні для бізнес-логіки та робочого процесу. Вони допомагають користувачам додатків або розробникам зрозуміти, в чому саме полягає проблема
- Вловлювати та надавати конкретну обробку підмножині існуючих винятків Java
Винятки Java можна перевіряти та не перевіряти. У наступних розділах ми розглянемо обидва ці випадки.
3. Спеціальний перевірений виняток
Перевірені винятки - це винятки, з якими потрібно поводитися явно.
Давайте розглянемо фрагмент коду, який повертає перший рядок файлу:
try (Scanner file = new Scanner(new File(fileName))) { if (file.hasNextLine()) return file.nextLine(); } catch(FileNotFoundException e) { // Logging, etc }
Наведений вище код є класичним способом обробки винятків, перевірених Java. Хоча код викидає FileNotFoundException, незрозуміло, в чому точна причина - чи файл не існує, чи ім'я файлу недійсне.
Щоб створити власний виняток, ми повинні розширити клас java.lang.Exception .
Давайте подивимось на приклад цього, створивши спеціально перевірений виняток, який називається IncorrectFileNameException:
public class IncorrectFileNameException extends Exception { public IncorrectFileNameException(String errorMessage) { super(errorMessage); } }
Зверніть увагу, що ми також повинні надати конструктор, який приймає рядок як повідомлення про помилку і називається конструктором батьківського класу.
Це все, що нам потрібно зробити, щоб визначити спеціальний виняток.
Далі, давайте подивимося, як ми можемо використовувати спеціальний виняток у нашому прикладі:
try (Scanner file = new Scanner(new File(fileName))) { if (file.hasNextLine()) return file.nextLine(); } catch (FileNotFoundException e) { if (!isCorrectFileName(fileName)) { throw new IncorrectFileNameException("Incorrect filename : " + fileName ); } //... }
Ми створили та використали спеціальний виняток, тому користувач тепер може знати, який саме виняток. Цього достатньо? Отже, ми втрачаємо першопричину винятку .
Щоб це виправити, ми також можемо додати параметр java.lang.Throwable до конструктора. Таким чином, ми можемо передати виняток root для виклику методу:
public IncorrectFileNameException(String errorMessage, Throwable err) { super(errorMessage, err); }
Зараз використовується IncorrectFileNameException разом із першопричиною винятку, як це:
try (Scanner file = new Scanner(new File(fileName))) { if (file.hasNextLine()) { return file.nextLine(); } } catch (FileNotFoundException err) { if (!isCorrectFileName(fileName)) { throw new IncorrectFileNameException( "Incorrect filename : " + fileName , err); } // ... }
Ось як ми можемо використовувати власні винятки, не втрачаючи першопричини, з якої вони виникли .
4. Спеціальний неперевірений виняток
У нашому тому ж прикладі припустимо, що нам потрібен спеціальний виняток, якщо ім’я файлу не містить розширення.
У цьому випадку нам знадобиться спеціальний неперевірений виняток, подібний до попереднього, оскільки ця помилка буде виявлена лише під час виконання.
Щоб створити власний непровірений виняток, нам потрібно розширити клас java.lang.RuntimeException :
public class IncorrectFileExtensionException extends RuntimeException { public IncorrectFileExtensionException(String errorMessage, Throwable err) { super(errorMessage, err); } }
Отже, ми можемо використати цей спеціальний неперевірений виняток у нашому прикладі:
try (Scanner file = new Scanner(new File(fileName))) { if (file.hasNextLine()) { return file.nextLine(); } else { throw new IllegalArgumentException("Non readable file"); } } catch (FileNotFoundException err) { if (!isCorrectFileName(fileName)) { throw new IncorrectFileNameException( "Incorrect filename : " + fileName , err); } //... } catch(IllegalArgumentException err) { if(!containsExtension(fileName)) { throw new IncorrectFileExtensionException( "Filename does not contain extension : " + fileName, err); } //... }
5. Висновок
Спеціальні винятки дуже корисні, коли нам потрібно обробляти конкретні винятки, пов'язані з бізнес-логікою. При правильному використанні вони можуть служити корисним інструментом для кращої обробки винятків та реєстрації.
Код для прикладів, використаних у цій статті, доступний на Github.