Kaedah memuktamadkan, antara muka boleh ditutup dan kenyataan cuba-dengan-sumber (Java 7) - 1

"Hai, Amigo!"

"Saya baru memutuskan untuk membincangkan kaedah muktamad () dengan anda."

"Jika anda masih ingat, finalize() ialah kaedah khas yang dipanggil oleh objek sebelum pemungut sampah memusnahkannya."

"Tujuan utama kaedah ini adalah untuk mengosongkan sumber luar bukan Java yang digunakan dengan menutup fail, aliran I/O dan sebagainya."

"Malangnya, kaedah ini tidak memenuhi jangkaan kami. Mesin maya Java boleh menangguhkan pemusnahan objek, serta memanggil kaedah pemuktamad, selagi ia mahu. Selain itu, ia tidak menjamin bahawa kaedah ini akan menjadi dipanggil sama sekali. Terdapat banyak situasi di mana ia tidak dipanggil, semuanya atas nama «pengoptimuman»."

"Saya ada dua rujukan untuk anda:"

Joshua Bloch telah menulis artikel yang bagus tentang kaedah ini: pautan
Saya akan menghuraikan petikan pendek:

  1. finalize() hanya boleh digunakan dalam dua kes:
    1. Untuk mengesahkan atau membersihkan sumber dengan pembalakan.
    2. Apabila bekerja dengan kod asli yang tidak penting kepada kebocoran sumber.
  2. finalize() menjadikan GC 430 kali lebih perlahan semasa membersihkan objek
  3. finalize() mungkin tidak dipanggil
Jika saya katakan dalam temu bual bahawa penamat adalah tongkat berbahaya dan berbahaya yang kewujudannya mengelirukan, adakah saya betul?

"Nah, itu membuat hari saya, Ellie."

"Java 7 mempunyai kenyataan baharu untuk menggantikan kaedah pemuktamadkan . Ia dipanggil try-with-resources . Ia sebenarnya bukan pengganti untuk finalize , sebaliknya ia adalah pendekatan alternatif."

"Adakah ia seperti cuba-tangkap, tetapi dengan sumber?"

"Ia hampir seperti cuba-tangkap . Perkara-perkaranya ialah, tidak seperti kaedah finalize (), blok akhirnya dalam kenyataan try- catch-finally sentiasa dilaksanakan. Pengaturcara juga telah menggunakan teknik ini apabila mereka perlu membebaskan sumber, tutup benang, dsb.

"Ini contoh:"

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

"Tidak kira sama ada blok cuba dilaksanakan dengan betul atau terdapat pengecualian, blok akhirnya akan sentiasa dipanggil dan mungkin untuk melepaskan sumber yang diduduki di sana."

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

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

"Pernyataan percubaan khas ini dipanggil cuba-dengan-sumber (serupa dengan cara koleksi mempunyai alternatif untuk dipanggil foreach )."

"Perhatikan bahawa selepas percubaan terdapat kurungan di mana pembolehubah diisytiharkan dan objek dicipta. Objek ini boleh digunakan di dalam blok cuba yang ditunjukkan oleh kurungan kerinting. Apabila blok cuba selesai dilaksanakan, tidak kira sama ada ia berakhir secara normal atau di sana. adalah pengecualian, kaedah close() akan dipanggil pada mana-mana objek yang dibuat di dalam kurungan."

"Menariknya! Notasi ini jauh lebih padat daripada yang sebelumnya. Saya tidak pasti saya memahaminya lagi."

"Ia tidak sesukar yang anda fikirkan."

"Jadi, bolehkah saya menentukan kelas setiap objek dalam kurungan?"

"Ya, sudah tentu, jika tidak kurungan tidak akan berguna."

"Dan jika saya perlu memanggil kaedah lain selepas keluar dari blok cuba, di manakah saya meletakkannya?"

"Perkaranya lebih halus di sini. Java 7 memperkenalkan antara muka berikut:"

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

"Kelas anda boleh melaksanakan antara muka ini. Dan kemudian anda boleh menggunakan objeknya di dalam pernyataan cuba-dengan-sumber. Hanya objek sedemikian boleh dibuat di dalam kurungan pernyataan cuba-dengan-sumber untuk «penutupan automatik»."

"Dengan kata lain, saya perlu mengatasi kaedah tutup dan menulis kod di dalamnya untuk «membersihkan» objek saya, dan saya tidak boleh menentukan kaedah lain?"

"Ya. Tetapi anda boleh menentukan beberapa objek—cuma pisahkannya dengan koma bertitik:"

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

"Itu lebih baik, tetapi tidak sehebat yang saya harapkan."

"Taklah teruk sangat. Awak akan terbiasa. Lama kelamaan."