Mempertimbangkan kode ini, dapatkah saya benar - benar yakin bahwa finally
blok selalu dijalankan, tidak peduli apa something()
itu?
try {
something();
return success;
}
catch (Exception e) {
return failure;
}
finally {
System.out.println("I don't know if this will get printed out");
}
java
error-handling
return
try-catch-finally
jonny lima
sumber
sumber
probably
.finally
; finalizer ==finalize()
metode.Jawaban:
Ya,
finally
akan dipanggil setelah eksekusi blok kodetry
ataucatch
.Satu-satunya waktu
finally
tidak akan dipanggil adalah:System.exit()
Runtime.getRuntime().halt(exitStatus)
try
ataucatch
kill -9 <pid>
pada UNIXfinally
blok akan dieksekusi oleh thread daemon dan semua thread non-daemon lainnya keluar sebelumfinally
dipanggilsumber
thread.stop()
tidak selalu mencegahfinally
blok dari dieksekusi.finally
blok akan dipanggil setelah itutry
blok, dan sebelum kontrol lolos ke pernyataan berikut. Itu konsisten dengan blok coba yang melibatkan loop tak terbatas dan karenanya blok akhirnya tidak pernah benar-benar dipanggil.Kode contoh:
Keluaran:
sumber
finally
-klik denganreturn 2;
tidak diperbolehkan (Kompiler-Kesalahan).Juga, meskipun itu praktik yang buruk, jika ada pernyataan pengembalian di dalam blok akhirnya, itu akan mengalahkan pengembalian lain dari blok biasa. Artinya, blok berikut ini akan kembali salah:
Hal yang sama dengan melempar pengecualian dari blok terakhir.
sumber
Inilah kata-kata resmi dari Spesifikasi Bahasa Jawa.
14.20.2. Eksekusi try-akhirnya dan try-catch-akhirnya
Spesifikasi untuk
return
sebenarnya membuat ini eksplisit:JLS 14.17 Pernyataan pengembalian
sumber
Selain tanggapan lain, penting untuk menunjukkan bahwa 'akhirnya' memiliki hak untuk menimpa setiap pengecualian / nilai yang dikembalikan oleh blok try..catch. Misalnya, kode berikut mengembalikan 12:
Demikian pula, metode berikut ini tidak membuang pengecualian:
Sementara metode berikut tidak membuangnya:
sumber
OutOfMemoryError
? ;)return retVal
setelah itufinally
blok, meskipun yang tentu saja mengasumsikan bahwa Anda ditekan beberapa pengecualian lain karena kode tidak akan masuk akal sebaliknya.Saya mencoba contoh di atas dengan sedikit modifikasi-
Output kode di atas:
Ini karena ketika
return i;
dieksekusii
memiliki nilai 2. Setelah ini,finally
blok dieksekusi di mana 12 ditugaskani
dan kemudianSystem.out
dieksekusi.Setelah mengeksekusi
finally
blok,try
blok mengembalikan 2, bukannya mengembalikan 12, karena pernyataan pengembalian ini tidak dieksekusi lagi.Jika Anda akan debug kode ini di Eclipse maka Anda akan mendapatkan perasaan bahwa setelah melaksanakan
System.out
darifinally
blokreturn
pernyataantry
blok dijalankan lagi. Tapi ini bukan masalahnya. Ini hanya mengembalikan nilai 2.sumber
i
itu bukan primitif, tetapi objek Integer.Inilah uraian jawaban Kevin . Penting untuk mengetahui bahwa ekspresi yang akan dikembalikan dievaluasi sebelumnya
finally
, bahkan jika itu dikembalikan setelah.Keluaran:
sumber
finally
. Menghitung nilai kembali (diprintX()
sini) masih ada sebelum itu.System.out.println("finally trumps return... sort of");
denganSystem.out.print("finally trumps return in try"); return 42;
Itulah seluruh ide dari blok akhirnya. Ini memungkinkan Anda memastikan Anda melakukan pembersihan yang mungkin dilewati karena Anda kembali, antara lain, tentu saja.
Akhirnya dipanggil terlepas dari apa yang terjadi di blok coba ( kecuali jika Anda menelepon
System.exit(int)
atau Java Virtual Machine menendang untuk beberapa alasan lain).sumber
Cara logis untuk memikirkan ini adalah:
sumber
akhirnya selalu dieksekusi kecuali ada penghentian program yang tidak normal (seperti memanggil System.exit (0) ..). jadi, sysout Anda akan dicetak
sumber
Kembali juga akhirnya akan membuang pengecualian. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
sumber
Blok akhirnya selalu dieksekusi kecuali ada penghentian program abnormal, baik yang disebabkan oleh crash JVM atau dari panggilan ke
System.exit(0)
.Selain itu, nilai apa pun yang dikembalikan dari dalam blok akhirnya akan menimpa nilai yang dikembalikan sebelum eksekusi blok akhirnya, jadi berhati-hatilah memeriksa semua titik keluar saat menggunakan coba akhirnya.
sumber
Tidak, tidak selalu satu kasus pengecualian adalah // System.exit (0); sebelum akhirnya blok mencegah akhirnya dieksekusi.
sumber
Akhirnya selalu dijalankan itulah intinya, hanya karena itu muncul dalam kode setelah pengembalian tidak berarti bahwa itulah yang diterapkan. Java runtime memiliki tanggung jawab untuk menjalankan kode ini saat keluar dari
try
blok.Misalnya jika Anda memiliki yang berikut:
Runtime akan menghasilkan sesuatu seperti ini:
Jika eksepsi yang tidak tertangkap dilemparkan
finally
blok akan berjalan dan eksepsi akan terus merambat.sumber
Ini karena Anda menetapkan nilai i sebagai 12, tetapi tidak mengembalikan nilai i ke fungsi. Kode yang benar adalah sebagai berikut:
sumber
Karena blok akhirnya akan selalu dipanggil kecuali jika Anda menelepon
System.exit()
(atau utas macet).sumber
Secara ringkas, dalam Dokumentasi Java resmi (Klik di sini ), tertulis bahwa -
sumber
MEMASUKKAN:
KELUARAN:
sumber
Ya itu akan dipanggil. Itulah inti dari akhirnya memiliki kata kunci. Jika melompat keluar dari blok coba / tangkap hanya bisa melewati blok akhirnya itu sama dengan menempatkan System.out.println di luar coba / tangkap.
sumber
Ya, akhirnya blok selalu dijalankan. Sebagian besar pengembang menggunakan blok ini untuk menutup koneksi database, objek resultset, objek pernyataan dan juga menggunakan hibernate java untuk mengembalikan transaksi.
sumber
TIDAK SELALU
The Java Bahasa spesifikasi menjelaskan bagaimana
try
-catch
-finally
dantry
-catch
blok bekerja di 14.20.2Dalam tidak ada tempat itu menetapkan bahwa
finally
blok selalu dieksekusi. Tetapi untuk semua kasus di manatry
-catch
-finally
dantry
-finally
blok menyelesaikannya tidak menentukan bahwa sebelum penyelesaianfinally
harus dijalankan.JLS tidak menjamin bahwa FIN dijalankan setelah KODE . JLS menjamin bahwa jika CODE dan NEXT dieksekusi maka FIN akan selalu dieksekusi setelah CODE dan sebelum NEXT .
Mengapa JLS tidak menjamin bahwa
finally
blok selalu dieksekusi setelahtry
blok? Karena itu tidak mungkin. Tidak mungkin tetapi mungkin bahwa JVM akan dibatalkan (membunuh, crash, matikan) setelah menyelesaikantry
blok tetapi sebelum eksekusifinally
blok. Tidak ada yang bisa dilakukan JLS untuk menghindari ini.Dengan demikian, setiap perangkat lunak yang untuk perilaku yang tepat tergantung pada
finally
blok yang selalu dieksekusi setelahtry
blok mereka selesai disadap.return
instruksi dalamtry
blok tidak relevan dengan masalah ini. Jika eksekusi mencapai kode setelahtry
-catch
-finally
dijamin bahwafinally
blok akan dieksekusi sebelumnya, dengan atau tanpareturn
instruksi di dalamtry
blok.sumber
Ya, tentu saja. Apa pun yang terjadi dalam blok coba atau tangkap Anda kecuali jika System.exit () dipanggil atau JVM lumpuh. jika ada pernyataan kembali di blok, akhirnya akan dieksekusi sebelum pernyataan kembali itu.
sumber
Ya, tentu saja. Satu-satunya hal yang tidak akan terjadi adalah JVM keluar atau macet
sumber
Menambahkan ke jawaban @ vibhash karena tidak ada jawaban lain yang menjelaskan apa yang terjadi dalam kasus objek yang bisa berubah seperti di bawah ini.
Akan menghasilkan
sumber
Saya mencoba ini, ini adalah utas tunggal.
The
main
Thread
akan berada diwait
negara selamanya, makafinally
tidak akan pernah disebut ,jadi output konsol tidak akan
print
String
: setelahwait()
ataufinally
Setuju dengan @Stephen C, contoh di atas adalah salah satu dari 3 kasus yang disebutkan di sini :
Menambahkan beberapa kemungkinan loop tak terhingga dalam kode berikut:
Kasus 2: Jika JVM crash terlebih dahulu
Ref: Bagaimana Anda menabrak JVM?
Kasus 6: Jika
finally
blok akan dieksekusi oleh daemonThread
dan semua non-daemonThreads
keluar sebelumnyafinally
dipanggil.output: Ini tidak mencetak "akhirnya" yang menyiratkan "Akhirnya blok" di "daemon thread" tidak dijalankan
sumber
Pertimbangkan program berikut:
Pada Java 1.8.162, blok kode di atas memberikan output berikut:
ini berarti bahwa menggunakan
finally
untuk membebaskan objek adalah praktik yang baik seperti kode berikut:sumber
sb.setLength(0)
pada akhirnya?sb = null;
hanya menambahkan kode yang tidak dibutuhkan. Saya mengerti maksud Anda bahwafinally
blok adalah tempat yang bagus untuk sumber daya gratis seperti koneksi database atau sesuatu seperti itu, tetapi perlu diingat bahwa contoh Anda dapat membingungkan pendatang baru.System.out.println("---AGAIN2---");
System.out.println(sb);
dan sekarang lebih jelas. Karena itu, hasilnya bertentangan dengan tesis Anda: p Saya juga menambahkan jawaban Anda, tetapi hasil edit harus diterima oleh moderator atau orang seperti itu. Jika tidak, Anda dapat menambahkannyaItu sebenarnya benar dalam bahasa apa pun ... akhirnya akan selalu dieksekusi sebelum pernyataan kembali, tidak peduli di mana pengembalian itu dalam tubuh metode. Jika bukan itu masalahnya, blok akhirnya tidak akan memiliki banyak arti.
sumber
Selain poin tentang pengembalian akhirnya menggantikan pengembalian di blok percobaan, hal yang sama berlaku untuk pengecualian. Blok akhirnya yang melempar pengecualian akan menggantikan pengembalian atau pengecualian yang dilemparkan dari dalam blok try.
sumber
finally
akan mengeksekusi dan itu sudah pasti.finally
tidak akan dieksekusi dalam kasus di bawah ini:kasus 1 :
Ketika Anda mengeksekusi
System.exit()
.kasus 2:
Saat JVM / Thread Anda mogok.
kasus 3:
Ketika eksekusi Anda dihentikan di antara secara manual.
sumber
sumber