JavaRush /Курси /JAVA 25 SELF /Прокидування винятків (throws)

Прокидування винятків (throws)

JAVA 25 SELF
Рівень 11 , Лекція 4
Відкрита

1. Вступ

У програмуванні часто трапляються ситуації, коли метод натрапляє на помилку, але не знає, як її правильно обробити. Наприклад, метод читає файл, але не знає, що робити, якщо файлу немає: запитати користувача? Завершити програму? Спробувати інший файл? У таких випадках метод може «перекласти відповідальність» на того, хто його викликав — тобто «прокинути» виняток далі ланцюгом викликів.

Прокидування винятку — це механізм, який дозволяє методу не обробляти помилку самостійно, а повідомити коду, який його викликає: «У мене тут проблема, розбирайтеся самі!».

Аналогія: Уявіть, що ви — працівник контакт-центру. Вам телефонує клієнт із питанням, на яке ви не знаєте відповіді. Замість того щоб гадати, ви кажете: «Одну мить, я зʼєднаю вас із фахівцем». Ви «прокидаєте» питання далі.

Ключове слово throws: як працює

У Java для прокидування винятків використовується ключове слово throws в оголошенні методу.

Синтаксис:

тип_поверненого_значення ім'яМетоду(...) throws ExceptionType 
{
    // код методу
}

Після throws вказується тип винятку, який може виникнути в цьому методі. Це як попередження для інших розробників: «Увага! Цей метод може кинути виняток певного типу. Будьте готові!»

Приклад:

public void readFile(String filename) throws FileNotFoundException 
{
    FileReader reader = new FileReader(filename); // може кинути FileNotFoundException
    // ...
}

У цьому прикладі метод readFile не обробляє помилку сам, а повідомляє: «Я можу кинути FileNotFoundException — нехай той, хто мене викликає, вирішує, що робити».

2. Як має реагувати метод, що викликає?

Якщо ви викликаєте метод, який оголошено з throws, у вас є два варіанти:

  • Обробити виняток за допомогою try-catch
  • Також прокинути виняток далі (додати throws у свій метод)

Варіант 1: обробити через try-catch

public static void main(String[] args) 
{
    try 
    {
        readFile("data.txt");
    } 
    catch (FileNotFoundException e) 
    {
        System.out.println("Файл не знайдено: " + e.getMessage());
    }
}

Тут ми перехоплюємо виняток і самі вирішуємо, що робити (наприклад, виводимо повідомлення користувачеві).

Варіант 2: прокинути далі

public static void main(String[] args) throws FileNotFoundException 
{
    readFile("data.txt");
}

Тепер відповідальність за обробку помилки лягає на того, хто викличе main. Зазвичай це JVM. Якщо помилку не оброблено, програма завершиться із повідомленням про помилку.

3. Приклад: читання файлу з прокидуванням винятку

Повний приклад з IOException і обробкою на рівні методу main:

import java.io.*;

public class FileDemo 
{
    // Метод оголошує, що може кинути IOException
    public static void printFirstLine(String filename) throws IOException 
    {
        BufferedReader reader = new BufferedReader(new FileReader(filename));
        String line = reader.readLine();
        System.out.println("Перший рядок: " + line);
        reader.close();
    }

    public static void main(String[] args) 
    {
        try 
        {
            printFirstLine("nofile.txt");
        } 
        catch (IOException e) 
        {
            System.out.println("Помилка під час читання файлу: " + e.getMessage());
        }
    }
}

Метод printFirstLine не знає, що робити, якщо файлу немає — він просто прокидує виняток. У методі main ми перехоплюємо помилку й виводимо повідомлення.

4. Корисні нюанси

Коли й навіщо використовувати прокидування винятків?

  • Коли метод не може або не повинен вирішувати, як обробляти помилку (наприклад, код бібліотеки).
  • Коли обробка помилки залежить від контексту (в одному випадку — завершити програму, в іншому — спробувати інший файл).
  • Щоб не засмічувати код зайвими try-catch там, де це не потрібно.

Найкраща практика: прокидуйте винятки, якщо не можете їх осмислено обробити. Не перехоплюйте винятки просто заради формальності!

Можна прокидувати кілька винятків

public void process() throws IOException, SQLException 
{
    // ...
}

Перевірювані й неперевірювані винятки: нагадування

Перевірювані (checked) винятки (наприклад, IOException, SQLException) — компілятор вимагає їх обробки або прокидування.

Неперевірювані (unchecked) винятки (наприклад, NullPointerException, IllegalArgumentException) — компілятор не вимагає їх обробляти; їх можна не зазначати в throws.

5. Типові помилки під час прокидування винятків

Помилка № 1: забули оголосити throws для перевірюваного винятку (checked).
Якщо метод може кинути перевірюваний виняток, але ви не оголосили його в throws і не обробили через try-catch, компілятор видасть помилку.

Помилка № 2: перехоплюєте виняток, але не обробляєте його.
Писати catch (Exception e) { } — погана практика! Краще прокинути виняток далі, якщо ви не знаєте, що з ним робити.

Помилка № 3: прокидуєте надто загальний тип.
Якщо метод може кинути лише FileNotFoundException, не вказуйте throws Exception — це ускладнює розуміння коду.

Помилка № 4: вказуєте неперевірювані винятки у throws.
Немає сенсу писати throws NullPointerException — компілятор цього не вимагає, і це не допомагає обробці помилок.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ