Apakah menangkap basah merupakan praktik yang buruk Throwable
?
Contohnya seperti ini:
try {
// Some code
} catch(Throwable e) {
// handle the exception
}
Apakah ini praktik yang buruk atau kita harus sespesifik mungkin?
java
exception-handling
throwable
ktulinho.dll
sumber
sumber
Jawaban:
Anda harus sespesifik mungkin. Jika tidak, serangga yang tidak terduga mungkin akan merayap dengan cara ini.
Selain itu,
Throwable
selimutError
juga dan itu biasanya tidak ada gunanya kembali . Anda tidak ingin menangkap / mengatasinya, Anda ingin program Anda segera mati sehingga Anda dapat memperbaikinya dengan baik.sumber
Ini ide yang buruk. Bahkan, menangkap
Exception
biasanya merupakan ide yang buruk. Mari pertimbangkan sebuah contoh:Sekarang, katakanlah getUserInput () memblokir untuk sementara, dan thread lain menghentikan thread Anda dengan cara yang paling buruk (ia memanggil thread.stop ()). Blok tangkapan Anda akan menemukan
ThreadDeath
Kesalahan. Ini sangat buruk. Perilaku kode Anda setelah menangkap Exception tersebut sebagian besar tidak ditentukan.Masalah serupa terjadi dengan menangkap Exception. Mungkin
getUserInput()
gagal karena InterruptException, atau pengecualian izin ditolak saat mencoba mencatat hasil, atau segala macam kegagalan lainnya. Anda tidak tahu apa yang salah, karena itu, Anda juga tidak tahu bagaimana cara mengatasi masalah tersebut.Anda memiliki tiga opsi yang lebih baik:
1 - Tangkap persis Pengecualian yang Anda tahu cara menanganinya:
2 - Lempar kembali pengecualian yang Anda hadapi dan tidak tahu cara menanganinya:
3 - Gunakan blok terakhir sehingga Anda tidak perlu ingat untuk melempar ulang:
sumber
throw new Exception("Some additional info, eg. userId " + userId, e);
. Ini akan dicatat dalam satu pengecualian bagus dengan 10 penyebab.Perlu diketahui juga bahwa saat menangkap
Throwable
, Anda juga bisa menangkapInterruptedException
yang membutuhkan perlakuan khusus. Lihat Dealing with InterruptedException untuk detail selengkapnya.Jika Anda hanya ingin menangkap pengecualian yang tidak dicentang, Anda juga dapat mempertimbangkan pola ini
Dengan cara ini, saat Anda memodifikasi kode dan menambahkan panggilan metode yang dapat memunculkan pengecualian yang dicentang, kompilator akan mengingatkan Anda tentang itu dan kemudian Anda dapat memutuskan apa yang harus dilakukan untuk kasus ini.
sumber
langsung dari javadoc kelas Error (yang merekomendasikan untuk tidak menangkap ini):
sumber
Ini bukan praktik yang buruk jika Anda sama sekali tidak dapat mengeluarkan gelembung pengecualian dari suatu metode.
Ini praktik yang buruk jika Anda benar-benar tidak dapat menangani pengecualian. Lebih baik menambahkan "lemparan" ke tanda tangan metode daripada hanya menangkap dan melempar ulang atau, lebih buruk lagi, membungkusnya dalam RuntimeException dan lemparan ulang.
sumber
Throwable
contoh - misalnya untuk pencatatan pengecualian khusus.Catching Throwable terkadang diperlukan jika Anda menggunakan pustaka yang melempar Kesalahan secara berlebihan, jika tidak, pustaka Anda dapat mematikan aplikasi Anda.
Namun, akan lebih baik dalam keadaan ini untuk menentukan hanya kesalahan spesifik yang dilemparkan oleh perpustakaan, daripada semua Throwable.
sumber
Throwable adalah kelas dasar untuk semua kelas yang dapat dilempar (tidak hanya pengecualian). Ada sedikit yang dapat Anda lakukan jika Anda menangkap OutOfMemoryError atau KernelError (lihat Kapan menangkap java.lang.Error? )
menangkap Pengecualian seharusnya cukup.
sumber
itu tergantung pada logika Anda atau untuk lebih spesifik pada pilihan / kemungkinan Anda. Jika ada pengecualian khusus yang mungkin dapat Anda tanggapi dengan cara yang berarti, Anda dapat menangkapnya terlebih dahulu dan melakukannya.
Jika tidak ada dan Anda yakin akan melakukan hal yang sama untuk semua pengecualian dan kesalahan (misalnya keluar dengan pesan kesalahan), daripada menangkap throwable itu tidak masalah.
Biasanya kasing pertama tahan dan Anda tidak akan menangkap lemparan. Tetapi masih ada banyak kasus di mana penangkapan itu berfungsi dengan baik.
sumber
Meskipun ini digambarkan sebagai praktik yang sangat buruk, terkadang Anda mungkin menganggapnya langka kasus yang tidak hanya berguna tetapi juga wajib. Berikut dua contoh.
Dalam aplikasi web di mana Anda harus menunjukkan halaman kesalahan penuh arti kepada pengguna. Kode ini memastikan ini terjadi karena ini besar di
try/catch
sekitar semua penangan permintaan Anda (servlet, aksi struts, atau pengontrol apa pun ....)}
Sebagai contoh lain, pertimbangkan Anda memiliki kelas layanan yang melayani bisnis transfer dana. Metode ini mengembalikan
TransferReceipt
jika transfer selesai atauNULL
jika tidak bisa.Sekarang pencitraan Anda mendapatkan
List
transfer dana dari pengguna dan Anda harus menggunakan layanan di atas untuk melakukan semuanya.Tetapi apa yang akan terjadi jika ada pengecualian? Anda tidak boleh berhenti, karena satu transfer mungkin berhasil dan satu mungkin tidak, Anda harus terus melanjutkan melalui semua pengguna
List
, dan menunjukkan hasil untuk setiap transfer. Jadi Anda berakhir dengan kode ini.Anda dapat menjelajahi banyak proyek sumber terbuka untuk melihat
throwable
apakah benar-benar di-cache dan ditangani. Misalnya di sini adalah pencariantomcat
,struts2
danprimefaces
:https://github.com/apache/tomcat/search?utf8=%E2%9C%93&q=catch%28Throwable https://github.com/apache/struts/search?utf8=%E2%9C%93&q=catch % 28 Throwable https://github.com/primefaces/primefaces/search?utf8=%E2%9C%93&q=catch%28Throwable
sumber
throwable
, itulah pertanyaan tentang apa iniPertanyaannya agak kabur; apakah Anda bertanya "apakah boleh menangkap
Throwable
", atau "apakahThrowable
boleh menangkap dan tidak melakukan apa-apa"? Banyak orang di sini menjawab yang terakhir, tapi itu masalah sampingan; 99% dari waktu Anda tidak harus "mengkonsumsi" atau membuang pengecualian, apakah Anda menangkapThrowable
atauIOException
atau apa pun.Jika Anda menyebarkan pengecualian, jawabannya (seperti jawaban untuk begitu banyak pertanyaan) adalah "tergantung". Itu tergantung pada apa yang Anda lakukan dengan pengecualian — mengapa Anda menangkapnya.
Contoh yang baik mengapa Anda ingin menangkapnya
Throwable
adalah dengan menyediakan semacam pembersihan jika ada kesalahan. Misalnya di JDBC, jika terjadi kesalahan selama transaksi, Anda ingin mengembalikan transaksi tersebut:Perhatikan bahwa pengecualian tidak dibuang, tetapi disebarkan.
Tetapi sebagai kebijakan umum, menangkap
Throwable
karena Anda tidak punya alasan dan terlalu malas untuk melihat pengecualian spesifik mana yang dilemparkan adalah bentuk yang buruk dan ide yang buruk.sumber
Secara umum Anda ingin menghindari penangkapan
Error
tetapi saya dapat memikirkan (setidaknya) dua kasus spesifik yang pantas untuk dilakukan:AssertionError
yang tidak berbahaya.sumber
Jika kita menggunakan throwable , maka itu juga mencakup Error dan hanya itu.
Contoh.
}
Keluaran:
sumber
Throwable adalah kelas super dari semua kesalahan dan eksesi. Jika Anda menggunakan Throwable in a catch clause, tidak hanya menangkap semua pengecualian, tetapi juga menangkap semua kesalahan. Kesalahan dilemparkan oleh JVM untuk menunjukkan masalah serius yang tidak dimaksudkan untuk ditangani oleh aplikasi. Contoh umum untuk itu adalah OutOfMemoryError atau StackOverflowError. Keduanya disebabkan oleh situasi yang berada di luar kendali aplikasi dan tidak dapat ditangani. Jadi Anda tidak boleh menangkap Throwable kecuali Anda cukup yakin bahwa itu hanya pengecualian yang berada di dalam Throwable.
sumber
Meskipun umumnya praktik yang buruk untuk menangkap Throwable (seperti yang dijelaskan oleh banyak jawaban pada pertanyaan ini), skenario di mana penangkapan
Throwable
berguna cukup umum. Izinkan saya menjelaskan satu kasus yang saya gunakan di pekerjaan saya, dengan contoh yang disederhanakan.Pertimbangkan metode yang melakukan penambahan dua angka, dan setelah penambahan berhasil, metode ini mengirimkan peringatan email ke orang-orang tertentu. Asumsikan bahwa nomor yang dikembalikan penting dan digunakan oleh metode panggilan.
Kode untuk mengirim peringatan email membaca banyak konfigurasi sistem dan karenanya, mungkin ada berbagai pengecualian yang dilemparkan dari blok kode itu. Namun kami tidak ingin pengecualian apa pun yang ditemukan selama pengiriman peringatan diterapkan ke metode pemanggil, karena metode tersebut hanya berkaitan dengan jumlah dari dua nilai Integer yang disediakannya. Oleh karena itu, kode untuk mengirimkan peringatan email ditempatkan dalam satu
try-catch
blok, di manaThrowable
tertangkap dan pengecualian apa pun hanya dicatat, memungkinkan sisa aliran untuk melanjutkan.sumber
Exception
dengan segala cara, tapi tidakThrowable
.