Что такое final и finally, и чем они отличаются?

В Java final и finally — это два совершенно разных элемента языка, несмотря на схожесть названия. Они относятся к разным частям языка: final — это ключевое слово, а finally — это блок управления потоком исполнения.

Разберём их по отдельности, затем сравним.

🔑 final — модификатор

final используется для объявления "неизменяемости". Он может применяться к:

  • переменным,

  • методам,

  • классам.

1. final переменная

  • Значение можно присвоить только один раз.

  • После этого изменить нельзя.

final int x = 10;
x = 20; // ошибка компиляции
  • Для объектов:
    • final MyClass obj = new MyClass(); — нельзя переназначить obj,
      но можно менять содержимое объекта (если он не immutable).

2. final метод

  • Метод нельзя переопределить в подклассе.
class Parent {
final void sayHello() {
System.out.println("Hello");
}
}
class Child extends Parent {
void sayHello() {} // ошибка компиляции
}

3. final класс

  • Класс нельзя наследовать.
final class Utils {
// ...
}
class MyUtils extends Utils {} // ошибка компиляции

⚙️ finally — блок в конструкции try-catch-finally

finally — это блок, который всегда выполняется, вне зависимости от того, произошло исключение или нет. Он используется для освобождения ресурсов (закрытие файлов, потоков, соединений).

Пример:

try {
int x = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Ошибка: деление на ноль");
} finally {
System.out.println("Этот блок выполнится всегда");
}
  • Даже если в try будет return или throw, блок finally всё равно выполнится.

  • Исключение: если процесс был завершён принудительно (System.exit(0)), finally не выполнится.

📌 Отличия final и finally

Критерий final finally
Что это Ключевое слово (модификатор) Блок кода (часть конструкции try)
--- --- ---
Где используется Переменные, методы, классы В конструкции try-catch-finally
--- --- ---
Назначение Запрет изменений/наследования Гарантированное выполнение кода
--- --- ---
Когда выполняется Во время компиляции Во время выполнения
--- --- ---
Может ли влиять на поток исполнения Нет Да, выполняется всегда при выходе из try
--- --- ---

🧠 Дополнительно

  • Не путай final с finally, и тем более с finalize() — последний был методом, вызываемым перед уничтожением объекта, но он устарел и удалён с Java 9+.

  • Хорошая практика — всегда использовать finally для освобождения ресурсов или вместо него использовать try-with-resources.

Таким образом:

  • final → ограничивает возможность изменения (переменных, методов, классов).

  • finally → гарантирует выполнение блока кода после try/catch.

Они выглядят похоже, но относятся к разным аспектам Java — синтаксису, семантике и этапу исполнения.