JavaRush /Курсы /Java Multithreading /Метод finalize, интерфейс closeable, try-with-resources(j...

Метод finalize, интерфейс closeable, try-with-resources(java7)

Java Multithreading
1 уровень , 9 лекция
Открыта
Метод 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(…);
}

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

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

Комментарии (125)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Никита Уровень 37
1 октября 2025
если в чате есть питонисты, то там аналогичная история (как и во многих других аспектах): В Python есть деструкторы классов __del__(), которые можно сказать аналогичны методу finalize() в Java. Нет никаких гарантий, что код деструктора будет выполнен. Поэтому в Python рекомендуется для выполнения кода по освобождению ресурсов использовать контекстный менеджер with (аналог try-with-resources), а в классе всю логику переносить в метод __exit__ (или __aexit__ при поддержки асинхронности).
Anonymous #3585174 Уровень 33
23 сентября 2025
Like
No Name Уровень 36
20 ноября 2024
+ лекция в копилке
VAKHANDER Уровень 32
30 октября 2024
30.10.2024
Борис Уровень 33
24 сентября 2024
очень мутно объяснено... "А если мне нужно вызвать другой метод при выходе из блока try, где мне его указать?" Какой "другой" метод?
4el0vek3 Уровень 36
18 августа 2025
Любой метод кроме close()...
Бромгексин Уровень 38
6 августа 2024
а что в таком случае нужно будет нужно написать в методе close() ??? типо просто так ты своему объекту не скажешь закрыться
Anemon Уровень 13 Expert
16 ноября 2024
Тебе, как создателю объекта, виднее как ему правильно закрываться. Обычно объекты не надо закрывать, но нужно закрывать такие вещи как файлы, некоторые потоки и прочее. Главное помнить об этом, ты туда можешь что угодно впихнуть в качестве метода close()
Максим Li Уровень 40
18 мая 2024
18.05.2024
YUREC Уровень 36
23 марта 2024
Эта лекция очень бы была кстати в разделе синктакс на 16 уровне, хотя try with resourses на том уровне объяснено лучше других тем.
Ислам Уровень 33
20 февраля 2024
Полезно
Anonymous #3390940 Уровень 38
18 февраля 2024
🦝