— Привіт, Аміго!
Давай ще раз обговоримо метод 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(…);
}
— Вже краще, але не так круто, як я сподівався.
— Все не так погано, ти звикнеш. З часом.