Pada pertanyaan untuk Java di universitas, ada cuplikan kode ini:
class MyExc1 extends Exception {}
class MyExc2 extends Exception {}
class MyExc3 extends MyExc2 {}
public class C1 {
public static void main(String[] args) throws Exception {
try {
System.out.print(1);
q();
}
catch (Exception i) {
throw new MyExc2();
}
finally {
System.out.print(2);
throw new MyExc1();
}
}
static void q() throws Exception {
try {
throw new MyExc1();
}
catch (Exception y) {
}
finally {
System.out.print(3);
throw new Exception();
}
}
}
Saya diminta memberikan hasilnya. Saya menjawab 13Exception in thread main MyExc2
, tetapi jawaban yang benar adalah 132Exception in thread main MyExc1
. Kenapa begitu? Saya tidak bisa mengerti ke mana perginya MyExc2
.
Inilah yang dikatakan Wikipedia tentang akhirnya klausa:
Mari kita membedah program Anda.
Jadi,
1
akan di-output ke layar, laluq()
dipanggil. Diq()
, pengecualian dilemparkan. Pengecualian kemudian ditangkapException y
tetapi tidak melakukan apa pun. Sebuah akhirnya klausul kemudian dieksekusi (itu), jadi,3
akan dicetak ke layar. Karena (dalam metodeq()
ada pengecualian yang dilemparkan dalam klausa terakhir , jugaq()
metode yang melewatkan pengecualian ke tumpukan induk (denganthrows Exception
di dalam deklarasi metode)new Exception()
akan dibuang dan ditangkap olehcatch ( Exception i )
,MyExc2
pengecualian akan dilemparkan (untuk saat ini tambahkan ke tumpukan pengecualian ), tetapi akhirnya dimain
blok akan dieksekusi terlebih dahulu.Jadi di,
Sebuah akhirnya klausa disebut ... (ingat, kita baru saja tertangkap
Exception i
dan dibuangMyExc2
) pada dasarnya,2
dicetak pada layar ... dan setelah2
dicetak di layar, sebuahMyExc1
pengecualian dilemparkan.MyExc1
ditangani denganpublic static void main(...)
metode ini.Keluaran:
Dosen benar! :-)
Pada intinya , jika Anda memiliki akhirnya dalam klausa try / catch, finally akan dieksekusi ( setelah menangkap pengecualian sebelum melemparkan pengecualian tertangkap keluar)
sumber
catch
dieksekusi sejakq()
melemparkan sebuahException
darifinally
bloknya sendiri .q
melalui eksekusi kecatch
blok kosong diq
(yang menelan pengecualian ini), lalu kefinally
blok dalamq
. Kata akhirnya blok cetakan3
, kemudian melemparkan pengecualian baru, yang berkatq
'sthrows Exception
dilewatkan sampai tumpukan ke orangtua.Pengecualian di blok akhirnya menggantikan pengecualian di blok tangkap.
Mengutip dari Bahasa Jawa Spesifikasi 14 edisi :
sumber
Akhirnya klausa dieksekusi bahkan ketika pengecualian dilempar dari mana saja di blok try / catch.
Karena itu adalah yang terakhir dieksekusi di dalam
main
dan itu melempar pengecualian, itulah pengecualian yang dilihat penelepon.Oleh karena itu pentingnya memastikan bahwa
finally
klausa tidak membuang apa pun, karena dapat menelan pengecualian daritry
blok.sumber
Sebuah
method
tidak bisathrow
dua pengecualian pada waktu yang sama. Itu akan selalu membuang yang terakhir terlemparexception
, yang dalam hal ini akan selalu menjadi yang darifinally
blok.Ketika pengecualian pertama dari metode
q()
dilempar, ia akan ditangkap dan kemudian ditelan oleh pengecualian blok akhirnya dilempar.q () -> dibuang
new Exception
->main
catch Exception
->throw
new Exception
->finally
melempar yang baruexception
(dan yang daricatch
"hilang")sumber
Cara termudah untuk memikirkan ini adalah membayangkan bahwa ada variabel global ke seluruh aplikasi yang menyimpan pengecualian saat ini.
Karena setiap pengecualian dilemparkan, "currentException" diatur ke pengecualian itu. Ketika aplikasi berakhir, jika currentException! = Null, maka runtime melaporkan kesalahan.
Juga, blok akhirnya selalu berjalan sebelum metode keluar. Anda kemudian dapat membalas potongan kode ke:
Urutan penerapan aplikasi adalah:
sumber
Diketahui bahwa blok akhirnya dieksekusi setelah coba dan tangkap dan selalu dieksekusi .... Tapi seperti yang Anda lihat itu agak rumit kadang-kadang memeriksa potongan kode di bawah ini dan Anda akan mengatakan bahwa pernyataan pengembalian dan melempar tidak selalu melakukan apa yang harus mereka lakukan sesuai urutan tema yang kita harapkan.
Bersulang.
sumber
Memesan:
https://www.compilejava.net/
sumber
Logikanya jelas sampai selesai dicetak
13
. Kemudian pengecualian dilemparkanq()
ditangkap olehcatch (Exception i)
dalammain()
dannew MyEx2()
siap untuk dilempar. Namun, sebelum melempar pengecualian,finally
blok harus dieksekusi terlebih dahulu. Kemudian output menjadi132
danfinally
meminta untuk melemparkan pengecualian lainnew MyEx1()
.Karena metode tidak dapat melempar lebih dari satu
Exception
, ia akan selalu membuang yang terbaruException
. Dengan kata lain, jika keduanyacatch
danfinally
balok mencoba untuk melemparException
, makaException
tangkapan yang masuk ditelan dan hanya pengecualian yangfinally
akan dilemparkan.Dengan demikian, dalam program ini, Pengecualian
MyEx2
ditelan danMyEx1
dibuang. Pengecualian ini dibuangmain()
dan tidak lagi tertangkap, sehingga JVM berhenti dan hasil akhirnya132Exception in thread main MyExc1
.Intinya, jika Anda memiliki
finally
dalamtry/catch
klausa, afinally
akan dieksekusi SETELAH menangkap pengecualian , tetapi SEBELUM melempar pengecualian yang tertangkap , dan HANYA pengecualian terakhir akan dilemparkan pada akhirnya .sumber
Saya pikir Anda hanya harus berjalan di
finally
blok:finally
diq
cetak "3".finally
dimain
cetak "2".sumber
Untuk menangani situasi semacam ini yaitu menangani pengecualian yang diajukan oleh akhirnya blok. Anda dapat mengelilingi blok akhirnya dengan mencoba blok: Lihat contoh di bawah ini dengan python:
sumber
Saya pikir ini menyelesaikan masalah:
sumber