Для чего используется блок `finally` в Java и приведи пример.

«Для чего используется блок `finally` в Java и приведи пример.» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Блок finally в Java используется в конструкции try-catch-finally для определения кода, который должен быть выполнен всегда, независимо от того, было ли выброшено исключение в блоке try или нет. Это гарантирует выполнение критически важных операций, таких как освобождение ресурсов (закрытие файлов, соединений с БД).

Ключевые особенности:

  • Блок finally выполняется после блока try и при наличии — после подходящего блока catch.
  • Он выполняется даже если:
    • Исключение было выброшено и перехвачено (catch).
    • Исключение было выброшено и НЕ перехвачено.
    • В блоке try или catch был выполнен return.
    • В блоке try или catch было выброшено необрабатываемое исключение (например, Error).
  • Единственные случаи, когда finally может не выполниться: аварийное завершение JVM (System.exit()) или сбой операционной системы.

Пример 1: Гарантированное закрытие ресурса (до Java 7):

FileInputStream fis = null;
try {
    fis = new FileInputStream("file.txt");
    // ... чтение файла
    int data = fis.read();
} catch (IOException e) {
    System.err.println("Ошибка чтения файла: " + e.getMessage());
} finally {
    // Этот блок выполнится ВСЕГДА
    if (fis != null) {
        try {
            fis.close(); // Гарантированное закрытие потока
        } catch (IOException e) {
            System.err.println("Ошибка при закрытии файла: " + e.getMessage());
        }
    }
    System.out.println("Блок finally выполнен.");
}

Пример 2: finally и return:

public static int testFinally() {
    try {
        System.out.println("Inside try");
        return 1; // Значение запоминается
    } catch (Exception e) {
        return 2;
    } finally {
        System.out.println("Inside finally"); // Выполнится ПЕРЕД возвратом из метода
        // return 3; // Если раскомментировать, метод ВСЕГДА вернет 3!
    }
}

public static void main(String[] args) {
    int result = testFinally();
    System.out.println("Result: " + result);
}
// Вывод:
// Inside try
// Inside finally
// Result: 1

Современная альтернатива (Java 7+): Начиная с Java 7, для автоматического управления ресурсами рекомендуется использовать try-with-resources, который неявно вызывает close() в блоке, аналогичном finally.

// Эквивалентно примеру 1, но короче и безопаснее
try (FileInputStream fis = new FileInputStream("file.txt")) {
    int data = fis.read();
    // ...
} catch (IOException e) {
    System.err.println("Ошибка: " + e.getMessage());
}
// Поток закроется автоматически после выхода из try-блока

Вывод: Блок finally — это фундаментальный механизм для обеспечения надежности кода и предотвращения утечек ресурсов. В современном коде для ресурсов, реализующих AutoCloseable, предпочтительнее использовать try-with-resources.