Metode finalisasi, antarmuka yang dapat ditutup, dan pernyataan coba-dengan-sumber daya (Java 7) - 1

"Hai, Amigo!"

"Saya baru saja memutuskan untuk mendiskusikan metode penyelesaian () dengan Anda."

"Jika Anda ingat, finalize() adalah metode khusus yang dipanggil oleh objek sebelum pengumpul sampah menghancurkannya."

"Tujuan utama metode ini adalah untuk membebaskan sumber daya eksternal non-Java yang telah digunakan dengan menutup file, aliran I/O, dan seterusnya."

"Sayangnya, metode ini tidak memenuhi harapan kami. Mesin virtual Java dapat menunda penghancuran objek, serta memanggil metode finalisasi, selama yang diinginkan. Selain itu, tidak menjamin bahwa metode ini akan dipanggil sama sekali. Ada banyak situasi di mana itu tidak dipanggil, semuanya atas nama «optimalisasi»."

"Saya punya dua referensi untuk Anda:"

Joshua Bloch telah menulis artikel bagus tentang metode ini: tautan
Saya akan mengutip kutipan singkat:

  1. finalize() hanya dapat digunakan dalam dua kasus:
    1. Untuk memverifikasi atau membersihkan sumber daya dengan logging.
    2. Saat bekerja dengan kode asli yang tidak penting untuk kebocoran sumber daya.
  2. finalize() membuat GC 430 kali lebih lambat dalam membersihkan objek
  3. finalize() mungkin tidak dipanggil
Jika saya mengatakan dalam sebuah wawancara bahwa finalisasi adalah kruk berbahaya dan berbahaya yang keberadaannya membingungkan, apakah saya benar?

"Yah, itu membuat hariku menyenangkan, Ellie."

"Java 7 memiliki pernyataan baru untuk menggantikan metode finalize . Ini disebut try-with-resources . Ini sebenarnya bukan pengganti finalize , melainkan pendekatan alternatif."

"Apakah ini seperti coba-coba, tetapi dengan sumber daya?"

"Ini hampir seperti try-catch . Masalahnya, tidak seperti metode finalize (), blok finally dalam pernyataan try- catch-finally selalu dieksekusi. Pemrogram juga menggunakan teknik ini ketika mereka perlu mengosongkan sumber daya, tutup utas, dll.

"Ini contohnya:"

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

"Terlepas dari apakah blok percobaan dieksekusi dengan benar atau ada pengecualian, blok akhirnya akan selalu dipanggil, dan memungkinkan untuk melepaskan sumber daya yang ditempati di sana."

"Jadi, di Java 7, keputusan dibuat untuk menjadikan pendekatan ini resmi, seperti:"

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

"Pernyataan try khusus ini disebut try-with-resources (mirip dengan bagaimana koleksi memiliki alternatif untuk dipanggil foreach )."

"Perhatikan bahwa setelah try ada tanda kurung di mana variabel dideklarasikan dan objek dibuat. Objek ini dapat digunakan di dalam blok try yang ditunjukkan oleh kurung kurawal. Ketika blok try selesai dieksekusi, terlepas dari apakah itu berakhir normal atau tidak pengecualian, metode close() akan dipanggil pada objek apa pun yang dibuat di dalam tanda kurung."

"Menarik sekali! Notasi ini jauh lebih ringkas dari yang sebelumnya. Aku tidak yakin aku belum memahaminya."

"Ini tidak sesulit yang kamu pikirkan."

"Jadi, bisakah saya menentukan kelas dari setiap objek dalam tanda kurung?"

"Ya, tentu saja, kalau tidak tanda kurung tidak akan berguna."

"Dan jika saya perlu memanggil metode lain setelah keluar dari blok percobaan, di mana saya harus meletakkannya?"

"Semuanya sedikit lebih halus di sini. Java 7 memperkenalkan antarmuka berikut:"

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

"Kelas Anda dapat mengimplementasikan antarmuka ini. Dan kemudian Anda dapat menggunakan objeknya di dalam pernyataan coba-dengan-sumber daya. Hanya objek semacam itu yang dapat dibuat di dalam tanda kurung pernyataan coba-dengan-sumber daya untuk «penutupan otomatis»."

"Dengan kata lain, saya perlu mengganti metode tutup dan menulis kode di dalamnya untuk «membersihkan» objek saya, dan saya tidak dapat menentukan metode lain?"

"Ya. Tapi Anda bisa menentukan beberapa objek—pisahkan saja dengan titik koma:"

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

"Itu lebih baik, tapi tidak sekeren yang kuharapkan."

"Tidak seburuk itu. Kamu akan terbiasa. Seiring waktu."