В чем разница между ключевым словом final и методом finalize() в Java?

«В чем разница между ключевым словом final и методом finalize() в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Это совершенно разные концепции: final — это ключевое слово для объявления константности, а finalize()устаревший метод сборки мусора.

Ключевое слово final

Применяется к переменным, методам и классам для наложения ограничений на изменение.

  1. final переменная (поле, локальная переменная, параметр):

    • Значение можно присвоить только один раз (константа или неизменяемая ссылка).
      final int MAX_USERS = 100;
      final List<String> list = new ArrayList<>(); // ссылка final, содержимое можно менять
      // list = new LinkedList<>(); // Ошибка компиляции: нельзя изменить ссылку
  2. final метод:

    • Не может быть переопределен (overridden) в подклассах. Гарантирует, что поведение метода останется неизменным.
      class Parent {
      public final void secureMethod() { /* логика */ }
      }
      class Child extends Parent {
      // @Override public void secureMethod() { } // Ошибка компиляции
      }
  3. final класс:

    • Не может быть унаследован (extended). Гарантирует, что реализация класса не будет изменена через наследование (например, String, Integer).
      final class UtilityClass { /* только статические методы */ }
      // class SubClass extends UtilityClass { } // Ошибка компиляции

Метод finalize()

  • Защищенный (protected) метод класса Object.
  • Историческое назначение: Вызывается сборщиком мусора (Garbage Collector, GC) перед удалением объекта, чтобы дать шанс освободить внешние ресурсы (например, закрыть файловый дескриптор).
  • Проблемы и статус:
    • Непредсказуемость: Время вызова (и будет ли он вызван вообще) не гарантируется.
    • Производительность: Замедляет работу GC.
    • Опасность: Может "воскресить" объект, создав новую сильную ссылку на него.
  • Современная альтернатива: Используйте try-with-resources и явное освобождение ресурсов (close()).
// Устаревший и нерекомендуемый подход
@Override
protected void finalize() throws Throwable {
    try {
        resource.close(); // Ненадежно!
    } finally {
        super.finalize();
    }
}

// Правильный современный подход (AutoCloseable)
try (FileInputStream fis = new FileInputStream("file.txt")) {
    // используем ресурс
} // ресурс закроется автоматически

Итог: final — важный инструмент проектирования для безопасности и ясности кода. finalize() — устаревший механизм, от которого следует отказаться в пользу AutoCloseable и явного управления ресурсами.