![Метод finalize, интерфейс closeable, try-with-resources(java7) - 1](https://cdn.javarush.com/images/article/e6882b0c-4466-408c-920e-f8e6823aab5d/original.jpeg)
— Привет, Амиго!
Я тут решила с тобой еще раз обсудить метод finalize().
Если ты помнишь, то finalize() – это специальный метод, который вызывается у объекта перед тем, как
сборщик мусора его уничтожит.
Основная цель этого метода – освободить используемые внешние не-Java ресурсы: закрыть файлы, потоки ввода-вывода и т.п.
К сожалению, этот метод не оправдывает возложенных на него надежд. Java-машина может отложить уничтожение объекта, как и вызов метода finalize на сколько угодно. Более того, она вообще не гарантирует, что этот метод будет вызван. В куче ситуаций ради «оптимизации» он не вызывается.
Приведу тебе две цитаты:
У Джошуа Блоха хорошо написано об этом методе: link Краткая выдержка:
|
Если я на собеседовании скажу, что 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(…);
}
— Уже лучше, но не так круто, как я надеялся.
— Все не так плохо, ты привыкнешь. Со временем.