Метод finalize

Модуль 2. Java Core
9 уровень , 4 лекция
Открыта
Метод finalize, интерфейс closeable, try-with-resources(java7) - 1

— Привет, Амиго!

Я тут решила с тобой еще раз обсудить метод finalize().

Если ты помнишь, то finalize() – это специальный метод, который вызывается у объекта перед тем, как
сборщик мусора его уничтожит.

Основная цель этого метода – освободить используемые внешние не-Java ресурсы: закрыть файлы, потоки ввода-вывода и т.п.

К сожалению, этот метод не оправдывает возложенных на него надежд. Java-машина может отложить уничтожение объекта, как и вызов метода finalize на сколько угодно. Более того, она вообще не гарантирует, что этот метод будет вызван. В куче ситуаций ради «оптимизации» он не вызывается.

Приведу тебе две цитаты:

У Джошуа Блоха хорошо написано об этом методе: link
Краткая выдержка:

  1. finalize() можно использовать только в двух случаях:
    1. Проверка/подчистка ресурсов с логированием.
    2. При работе с нативным кодом, который не критичен к утечке ресурсов.
  2. finalize() замедляет работу GC по очистке объекта в 430 раз
  3. finalize() может быть не вызван
Если я на собеседовании скажу, что finalize — это вредный и опасный костыль, который своим существованием сбивает с толку, то буду прав?

— М-да, обрадовала ты меня, Элли.

— На замену метода finalize в Java 7 появилась новая конструкция. Называется она – try-with-resources. Это не совсем замена finalize – скорее альтернативный подход.

— Как try-catch, только с ресурсами?

— Почти как try-catch. Дело в том, что в отличие от метода finalize(), блок finally из конструкции try-catch-finally вызывается всегда. Этим и пользовались программисты, когда нужно было гарантированно освободить ресурсы, закрыть потоки и т.д.
Пример:

InputStream is = null;
try
{
 is = new FileInputStream("c:/file.txt");
 is.read(…);
}
finally
{
 if (is != null)
 is.close();
}

Независимо от того, нормально ли отработал блок try, или там возникло исключение, блок finally вызовется всегда, и там можно будет освободить занятые ресурсы.

Поэтому в Java 7 этот подход решили сделать официальным, и вот что из этого вышло:

try(InputStream is = new FileInputStream("c:/file.txt"))
{
 is.read(…);
}

Это специальная конструкция try, называемая try-with-resources (так же как и второй for для коллекций называется foreach).

Обрати внимание – после try следуют круглые скобки, где объявляются переменные и создаются объекты. Эти объекты можно использовать внутри блока try, обозначенного скобками {}. Когда выполнение команд блока try закончится, независимо от того – нормально оно закончилось или было исключение, для объекта, созданного внутри круглых скобок (), будет вызван метод close();

— Как интересно. Такая запись гораздо компактнее, чем предыдущая. Понять бы ее еще.

— Все не так сложно, как ты думаешь.

— А я могу указывать в круглых скобках объекты своих классов?

— Да, конечно, иначе от этих скобок было бы мало пользы.

— А если мне нужно вызвать другой метод при выходе из блока try, где мне его указать?

— Тут все немного тоньше. В Java 7 появился такой интерфейс:

public interface AutoCloseable
{
 void close() throws Exception;
}

Ты можешь унаследовать свой класс от такого интерфейса. И тогда его объекты можно будет использовать внутри try-with-resources. Только объекты такого типа можно использовать внутри круглых скобок try-with-resources для «автоматического закрытия».

— Т.е. мне нужно будет переопределить метод close и написать в нем код по «очистке» моего объекта, а указать другой метод нельзя?

— Ага. Зато можно указывать несколько объектов, разделив их точкой с запятой:

try(
InputStream is = new FileInputStream("c:/file.txt");
OutputStream os = new FileOutputStream("c:/output.txt")
)
{
 is.read(…);
 os.write(…);
}

— Уже лучше, но не так круто, как я надеялся.

— Все не так плохо, ты привыкнешь. Со временем.

Комментарии (9)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Руслан Уровень 46
3 октября 2025
мега сраная задача с методом finalize ведь идея банально ничего не дает с ним сделать
Andrei A. Уровень 67
23 мая 2025
"У Джошуа Блоха хорошо написано об этом методе: link" ссылка не открывается http://www.informit.com/articles/article.aspx?p=1216151&seqNum=7
Дмитрий Уровень 49 Expert
10 июля 2024
— Т.е. мне нужно будет переопределить метод close и написать в нем код по «очистке» моего объекта, а указать другой метод нельзя? — Ага. Зато можно указывать несколько объектов, разделив их точкой с запятой: что "АГА"??????
Андрей Уровень 10
18 декабря 2024
АХАХАХАХА
9 октября 2023
Уже второй раз Амиго задает вопрос, а его игнорят. Обидно за железного приятеля
Misha Saharin Уровень 111 Expert
2 марта 2023
Важно:) никогда finalize не использовать. всегда, по возможности, стремится использовать конструкцию try-with-resources. всегда будет вызван метод close() если твой объект от interface AutoCloseable. тебе нужно будет переопределить метод close и написать в нем код по «очистке» объекта.
Ярослав Уровень 48 Expert
26 октября 2022
Метод finalize "вредный и опасный костыль", да и вообще он уже не актуален, так как вместо него придумали более удобный, "альтернативный подход". Показывать пример в лекции, как он вызывается и работает, мы соответственно не будем. Но запихнём в последнюю задачу, вместе с ещё не изученными методами sql, что бы ты не забывал насколько сильно подача материала может быть абсурдной и ленивой.
Евгений Уровень 109 Expert
24 июня 2024
👍
Владимир Уровень 48 Expert
5 мая 2022

— А если мне нужно вызвать другой метод при выходе из блока try, где мне его указать?
Что-то не понимаю в чём здесь проблема, ведь можно использовать блок finally в try-with-resources.