Menurut Joshua Bloch's Java Efektif (Edisi Kedua), ada dua skenario kapan finalize()
berguna:
Pertama adalah bertindak sebagai "jaring pengaman" jika pemilik benda lupa memanggil metode penghentian eksplisitnya. Meskipun tidak ada jaminan bahwa finalizer akan dipanggil segera, mungkin lebih baik untuk membebaskan sumber daya terlambat daripada tidak pernah, dalam kasus-kasus (mudah-mudahan jarang) ketika klien gagal memanggil metode penghentian eksplisit. Tetapi finalizer harus mencatat peringatan jika menemukan bahwa sumber daya belum diakhiri
Penggunaan sah kedua finalizers menyangkut objek dengan rekan asli. Peer asli adalah objek asli yang didelegasikan objek normal melalui metode asli. Karena peer asli bukan objek normal, pemulung tidak tahu tentang hal itu dan tidak dapat mengklaim kembali ketika peer Java-nya direklamasi. Finalizer adalah kendaraan yang tepat untuk melakukan tugas ini, dengan asumsi rekan asli tidak memiliki sumber daya penting. Jika rekan asli memegang sumber daya yang harus dihentikan segera, kelas harus memiliki metode penghentian eksplisit, seperti yang dijelaskan di atas. Metode penghentian harus melakukan apa pun yang diperlukan untuk membebaskan sumber daya kritis.
Untuk bacaan lebih lanjut, lihat Butir 7, halaman 27.
Finalizers penting untuk pengelolaan sumber daya asli. Misalnya, objek Anda mungkin perlu mengalokasikan WidgetHandle dari sistem operasi menggunakan API non-Java. Jika Anda tidak melepaskan WidgetHandle ketika objek Anda adalah GC, Anda akan membocorkan WidgetHandles.
Yang penting adalah bahwa "finalizer tidak pernah disebut" kasus rusak agak sederhana:
Dalam ketiga kasus ini, Anda juga tidak memiliki kebocoran asli (berdasarkan fakta bahwa program Anda tidak berjalan lagi), atau Anda sudah memiliki kebocoran non-asli (jika Anda terus mengalokasikan objek yang dikelola tanpa menjadi GC).
Peringatan "jangan mengandalkan finalizer yang dipanggil" sebenarnya tentang tidak menggunakan finalizer untuk logika program. Misalnya, Anda tidak ingin melacak berapa banyak objek Anda yang ada di semua contoh program Anda dengan menambah penghitung dalam file di suatu tempat selama konstruksi dan mengurangi itu dalam finalizer - karena tidak ada jaminan bahwa objek Anda akan diselesaikan, penghitung file ini mungkin tidak akan pernah kembali ke 0. Ini benar-benar kasus khusus dari prinsip yang lebih umum bahwa Anda tidak harus bergantung pada program Anda mengakhiri secara normal (gangguan listrik, dll).
Namun, untuk pengelolaan sumber daya asli, kasus di mana finalizer tidak berjalan sesuai dengan kasus di mana Anda tidak peduli jika tidak berjalan.
sumber
close()
tidak pernah dipanggil sebelum menjadi tidak terjangkau)Tujuan metode ini dijelaskan dalam dokumentasi API sebagai berikut:
Jika Anda juga tertarik pada alasan mengapa perancang bahasa telah memilih bahwa "objek dibuang secara tidak dapat ditarik kembali" ( sampah dikumpulkan ) dengan cara yang berada di luar kendali pemrogram aplikasi ("kita seharusnya tidak pernah mengandalkan"), ini telah dijelaskan dalam jawaban terkait pertanyaan :
Kutipan di atas, pada gilirannya, diambil dari dokumentasi resmi tentang tujuan desain Java , yang dapat dianggap referensi otoritatif menjelaskan mengapa desainer bahasa Jawa memutuskan dengan cara ini.
Untuk diskusi agnostik bahasa yang lebih rinci dan preferensi ini, lihat bagian OOSC 9.6 Manajemen memori otomatis (sebenarnya, tidak hanya bagian ini tetapi seluruh bab 9 sangat layak dibaca jika Anda tertarik pada hal-hal seperti itu). Bagian ini dibuka dengan pernyataan yang tidak ambigu:
sumber
Penyelesai ada karena mereka diharapkan menjadi sarana yang efektif untuk memastikan bahwa segala sesuatunya dibersihkan (meskipun dalam praktiknya tidak), dan karena ketika ditemukan, cara yang lebih baik untuk memastikan pembersihan (seperti referensi hantu dan percobaan dengan -resources) belum ada. Jika dipikir-pikir, Jawa mungkin akan lebih baik jika upaya yang dihabiskan untuk mengimplementasikan fasilitas "finalisasinya" telah dihabiskan untuk sarana pembersihan lainnya, tetapi itu hampir tidak jelas selama waktu Jawa awalnya dikembangkan.
sumber
CAVEAT: Saya mungkin ketinggalan zaman, tetapi ini adalah pemahaman saya beberapa tahun yang lalu:
Secara umum, tidak ada jaminan kapan finalis berjalan - atau bahkan itu berjalan sama sekali, meskipun beberapa JVM akan memungkinkan Anda meminta GC lengkap dan finalisasi sebelum program keluar (yang, tentu saja, berarti program membutuhkan waktu lebih lama untuk keluar, dan yang bukan mode operasi standar).
Dan beberapa GC diketahui secara eksplisit menunda atau menghindari objek GC'ing yang telah menyelesaikan, dengan harapan bahwa ini akan menghasilkan kinerja yang lebih baik pada tolok ukur.
Sayangnya, perilaku ini bertentangan dengan alasan asli yang disarankan oleh finalizer, dan telah mendorong penggunaan metode shutdown yang disebut secara eksplisit.
Jika Anda memiliki objek yang benar-benar harus dibersihkan sebelum dibuang, dan jika Anda benar-benar tidak dapat mempercayai pengguna untuk melakukannya, finalizer mungkin masih layak dipertimbangkan. Tetapi secara umum, ada Alasan Bagus bahwa Anda tidak melihatnya sesering dalam kode Java modern seperti yang Anda lakukan dalam beberapa contoh awal.
sumber
The Google Java Style Guide memiliki beberapa nasihat bijak pada subjek:
sumber
PhantomReference
danReferenceQueue
sebagai gantinya.PhantomReference
ini solusi yang lebih baik. Finalizers adalah kutil yang tersisa dari masa-masa awal Jawa, dan sejenisObject.clone()
dan mentah, adalah bagian dari bahasa yang paling terlupakan.The Java Language Specification (Java SE 7) menyatakan:
sumber