Dalam pengalaman saya, ada satu dan hanya satu alasan untuk mengganti Object.finalize()
, tetapi itu adalah alasan yang sangat bagus :
Untuk menempatkan kode logging kesalahan finalize()
yang memberi tahu Anda jika Anda pernah lupa untuk memohon close()
.
Analisis statis hanya dapat menangkap kelalaian dalam skenario penggunaan sepele, dan peringatan kompiler yang disebutkan dalam jawaban lain memiliki pandangan sederhana tentang hal-hal yang sebenarnya harus Anda nonaktifkan untuk menyelesaikan segala sesuatu yang non-sepele. (Saya memiliki lebih banyak peringatan yang diaktifkan daripada programmer lain yang saya kenal atau pernah dengar, tapi saya tidak mengaktifkan peringatan bodoh.)
Finalisasi tampaknya menjadi mekanisme yang baik untuk memastikan bahwa sumber daya tidak rusak, tetapi kebanyakan orang melihatnya dengan cara yang benar-benar salah: mereka menganggapnya sebagai mekanisme cadangan alternatif, perlindungan "kesempatan kedua" yang secara otomatis akan menyelamatkan hari dengan membuang sumber daya yang mereka lupa. Ini salah besar . Hanya ada satu cara untuk melakukan sesuatu: Anda selalu menutup semuanya, atau finalisasi selalu menutup semuanya. Tetapi karena finalisasi tidak dapat diandalkan, finalisasi tidak bisa seperti itu.
Jadi, ada skema ini yang saya sebut Pembuangan Wajib , dan menetapkan bahwa programmer bertanggung jawab untuk selalu secara eksplisit menutup segala sesuatu yang mengimplementasikan Closeable
atau AutoCloseable
. (Pernyataan coba-dengan-sumber daya masih dianggap sebagai penutupan eksplisit.) Tentu saja, programmer mungkin lupa, jadi di situlah finalisasi berperan, tetapi bukan sebagai peri ajaib yang secara ajaib akan membuat segalanya benar pada akhirnya: Jika finalisasi menemukan yang close()
tidak dipanggil, itu tidakmencoba untuk memohonnya, justru karena akan ada (dengan kepastian matematika) ada gerombolan programmer n00b yang akan bergantung padanya untuk melakukan pekerjaan yang mereka terlalu malas atau terlalu linglung untuk melakukannya. Jadi, dengan pembuangan wajib, ketika finalisasi menemukan yang close()
tidak diminta, itu mencatat pesan kesalahan merah terang, memberitahu programmer dengan huruf besar semua modal untuk memperbaiki dirinya, barang-barangnya.
Sebagai manfaat tambahan, rumor mengatakan bahwa "JVM akan mengabaikan metode finalisasi () sepele (misalnya yang hanya kembali tanpa melakukan apa pun, seperti yang didefinisikan dalam kelas Object)", sehingga dengan pembuangan wajib Anda dapat menghindari semua finalisasi overhead di seluruh sistem Anda ( lihat jawaban alip untuk informasi tentang seberapa buruk overhead ini) dengan mengkode finalize()
metode Anda seperti ini:
@Override
protected void finalize() throws Throwable
{
if( Global.DEBUG && !closed )
{
Log.Error( "FORGOT TO CLOSE THIS!" );
}
//super.finalize(); see alip's comment on why this should not be invoked.
}
Gagasan di balik ini adalah bahwa Global.DEBUG
adalah static final
variabel yang nilainya diketahui pada waktu kompilasi, jadi jika itu false
maka kompiler tidak akan memancarkan kode sama sekali untuk seluruh if
pernyataan, yang akan membuat ini finalizer sepele (kosong), yang pada gilirannya berarti bahwa kelas Anda akan diperlakukan seolah-olah tidak memiliki finalizer. (Dalam C # ini akan dilakukan dengan #if DEBUG
blok yang bagus , tapi apa yang bisa kita lakukan, ini java, di mana kita membayar kesederhanaan yang jelas dalam kode dengan overhead tambahan di otak.)
Lebih lanjut tentang Pembuangan Wajib, dengan diskusi tambahan tentang membuang sumber daya di dot Net, di sini: michael.gr: Pembuangan wajib vs kekejian "Buang-buang"
finalize()
agak kacau. Jika Anda pernah mengimplementasikannya, pastikan itu aman untuk semua metode lain pada objek yang sama.