Kata bahasa Inggris yang abnormal adalah pengecualian, dan terjemahan literal berarti "kecelakaan, pengecualian", yang berarti situasi abnormal. Faktanya, pengecualian pada dasarnya adalah kesalahan program, termasuk kesalahan logika program dan kesalahan sistem.
Kata Pengantar
Setiap orang akrab dengan penanganan pengecualian Java, secara umum, ada dua poin:
1. Lempar Pengecualian: Lempar Pengecualian
kelas SimpleException {public void a () melempar Exception {Throw New Exception (); };}2. Kecuali:
kelas publik myException {public static void main (string [] args) {myException e = new myException (); SimpleException SE = new SimpleException (); coba {se.a (); } catch (Exception e1) {e1.printstacktrace (); }}} kelas SimpleException {public void a () melempar Exception {throw new Exception (); };}Artikel ini akan membahas beberapa detail tentang basis yang lebih mendalam ini.
Dua kelas pengecualian khusus
Bahasa Java memberi kita banyak kelas pengecualian, tetapi kadang -kadang kita masih harus menyesuaikan kelas pengecualian untuk kenyamanan menulis kode:
kelas SimpleException memperluas Exception {};
Setelah kreasi, kita dapat menggunakan cobalah menangkapnya untuk menangkapnya:
kelas publik myException {public static void main (string [] args) {myException e = new myException (); coba {ea (); } catch (SimpleException E1) {E1.PrintStackTrace (); }} public void a () melempar SimpleException {throw new SimpleException (); }} kelas SimpleException memperluas Exception {};Kami mendefinisikan metode a () di MyException, biarkan itu melempar pengecualian Exception Simple, lalu kami menyebut metode ini di main () dan menangkap pengecualian ini menggunakan Coba Tangkap:
SimpleException at MyException.a(MyException.java:15) at MyException.main(MyException.java:8) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.delegatingmethodaccessorimpl.invoke (delegatingmethodacessorimpl.java:43) di java.lang.reflect.method.invoke (Method.java:606) di com.intellij.rt.execution.application.appmain
Hasilnya setelah kompilasi dan eksekusi terutama didasarkan pada tiga baris pertama. Berikut beberapa poin yang harus dijelaskan:
1. Tentukan tipe pengecualian: (spesifikasi pengecualian)
Ketika kita perlu melempar pengecualian dalam suatu metode, kita menggunakan lemparan dan menambahkan contoh kelas pengecualian. Program akan melempar pengecualian yang sesuai untuk program klien (program yang memanggil kode ini) dan keluar di sini (setara dengan kembali). Perhatikan juga bahwa kita harus menentukan jenis pengecualian saat mendefinisikan metode ini. Misalnya, kode berikut akan melempar pengecualian Exception sederhana
public void a () melempar SimpleException
2. Lemparkan beberapa pengecualian:
public void a () melempar SimpleException, AException, Bexception {Throw new SimpleException (); }Kelas pengecualian yang berbeda dapat dipisahkan oleh koma. Dalam hal ini, kita tidak perlu melempar setiap contoh kelas pengecualian (), tetapi kode klien harus menangkap setiap kelas pengecualian:
kelas publik myException {public static void main (string [] args) {myException e = new myException (); coba {ea (); } catch (SimpleException E1) {E1.PrintStackTrace (); } catch (bexception e1) {e1.printstacktrace (); } catch (aException e1) {e1.printstacktrace (); }} public void a () melempar SimpleException, AException, Bexception {Throw new SimpleException (); }} kelas SimpleException memperluas Exception {}; kelas AException memperluas Exception {} kelas Bexception memperluas Exception {} Tiga jejak tumpukan
Apakah itu melempar pengecualian atau menangkap dan menangani pengecualian, tujuan kami adalah untuk menulis program yang lebih kuat, yang tergantung pada sebagian besar informasi pengecualian yang disediakan oleh mekanisme pengecualian Java, dan pembawanya adalah jejak stack.
Dalam kode sebelumnya, kami langsung menggunakan printStackTrace () untuk mencetak informasi pengecualian. Bahkan, kami juga dapat menggunakan metode getStackTrace () untuk mendapatkan koleksi StacktraceElement. Jika Anda memiliki ide di tangan, terlebih dahulu Anda dapat mencari kelas StackTraceElement, dan Anda dapat menemukan bahwa itu mengimplementasikan antarmuka yang dapat di -serial, dan kemudian lihat deskripsi kelasnya:
/** * elemen dalam jejak tumpukan, seperti yang dikembalikan oleh {@link * Throwable#getStackTrace ()}. Setiap elemen mewakili bingkai tumpukan tunggal. * Semua bingkai tumpukan kecuali yang ada di bagian atas tumpukan mewakili * doa metode. Bingkai di bagian atas tumpukan mewakili titik eksekusi * di mana jejak tumpukan dihasilkan. Biasanya, * ini adalah titik di mana yang dapat dilempar sesuai dengan jejak tumpukan * dibuat. * * @since 1.4 * @author Josh Bloch */Jelas bahwa setiap contoh kelas ini adalah elemen dari jejak tumpukan, mewakili bingkai tumpukan, dan jejak tumpukan dikembalikan dengan metode getStackTrace (). Saya mencoba menerjemahkan beberapa kali berikut, tetapi saya merasa itu tidak baik, jadi saya bisa menulis kode secara langsung untuk menjelaskannya:
kelas publik myException {public static void main (string [] args) {myException e = new myException (); ea (); public void a () {coba {lempar pengecualian baru (); } catch (exception e) {stacktraceElement [] ste = e.getstacktrace (); System.out.println (ste.length); }}}Kami mendefinisikan metode A, biarkan itu melemparkan pengecualian pengecualian sambil menangkapnya, dan kemudian kami mendapatkan array stacktraceElement melalui metode getStackTrace () dan mencetak panjang array:
7
Proses selesai dengan kode keluar 0
Kami sedikit mengubah kode dan berhenti menangkap pengecualian di a. Kami mendefinisikan kembali metode B sehingga menangkap pengecualian saat memanggil A:
kelas publik myException {public static void main (string [] args) {myException e = new myException (); eb (); } public void b () {coba {a (); } catch (exception e) {stacktraceElement [] ste = e.getstacktrace (); System.out.println (ste.length); }} public void a () melempar pengecualian {lempar pengecualian baru (); }}Hasilnya adalah sebagai berikut:
8
Proses selesai dengan kode keluar 0
Jangan khawatir, mari kita lihat sesuatu yang menarik:
kelas publik myException {public static void main (string [] args) {myException exception = myException baru (); coba {exception.c (); } catch (exception e) {stacktraceElement [] ste = e.getstacktrace (); System.out.println (ste.length); System.out.println ("-----------------------------------------------------------"); untuk (StackTraceElement S: E.GetStackTrace ()) {System.out.println (s.getClassName ()+": Metode"+s.getMethodName ()+"di baris"+s.getlinEnumber ()); } System.out.println ("---------------------------------------------------------------"); }} public void c () melempar Exception {coba {a (); } catch (Exception e) {throw e; }} public void a () melempar pengecualian {lempar pengecualian baru (); }}Inilah hasilnya:
8 ------------------------------------------------- line57sun.reflect.DelegatingMethodAccessorImpl:method invoke at line43java.lang.reflect.Method:method invoke at line606com.intellij.rt.execution.application.AppMain:method main at line144---------------------------------------------------------------Process finished with exit code 0
Artinya, getStackTrace () mengembalikan tumpukan, yang berisi beberapa informasi dasar dari penelepon (main ()) ke pengecualian lemparan awal (a ()). Dalam kode di atas, kami menangkap pengecualian saat memanggil metode A dalam metode C dan melemparkannya lagi melalui lemparan. Metode yang memanggil metode C dapat menangkap dan menangani pengecualian, atau Anda dapat memilih untuk terus melempar untuk membiarkan penelepon tingkat tinggi (dekat bagian bawah tumpukan) menanganinya. Meskipun Rethrow sangat nyaman, ada beberapa masalah. Mari kita lihat kode berikut:
kelas publik myException {public static void main (string [] args) {myException exception = myException baru (); coba {exception.c (); } catch (Exception e) {E.PrintStackTrace (System.out); }} public void c () melempar Exception {coba {a (); } catch (Exception e) {throw e; }} public void a () melempar pengecualian {lempar pengecualian baru ("Pengecualian dari a ()"); }} java.lang.Exception: Pengecualian dari a () di myException.a (myException.java:40) di myException.c (myexception.java:30) di myException.main (myexception.java:21)Kami melontarkan kembali dalam C dan mencetaknya menggunakan E.PrintStackTrace () di Main. Anda dapat melihat bahwa jejak tumpukan yang dicetak masih menjadi milik a. Jika kita ingin mengubah jejak tumpukan menjadi C, kita dapat menulisnya seperti ini:
kelas publik myException {public static void main (string [] args) {myException exception = myException baru (); coba {exception.c (); } catch (Exception e) {E.PrintStackTrace (System.out); }} public void c () melempar Exception {coba {a (); } catch (Exception e) {// lempar e; lempar (pengecualian) e.fillinstacktrace (); }} public void a () melempar pengecualian {lempar pengecualian baru ("Pengecualian dari a ()"); }} java.lang.Exception: Pengecualian dari a () di myException.c (myException.java:22) di myException.main (myexception.java:10) Empat Pengecualian Rantai
Mari kita lihat skenario:
Public Class TestException {public static void main (string [] args) {testException testException = testException baru (); coba {testException.c (); } catch (cException e) {e.printstacktrace (); }} public void a () melempar AException {aException aexception = AException baru ("Ini adalah pengecualian"); Lempar Aeksepsi; } public void b () melempar Bexception {coba {a (); } catch (aException e) {lempar bexception baru ("Ini b exception"); }} public void c () melempar cException {coba {b (); } catch (bexception e) {lempar cException baru ("This is C Exception"); }}} kelas AException memperluas pengecualian {public aexception (string msg) {super (msg); }} kelas bexception memperluas pengecualian {public bexception (string msg) {super (msg); }} kelas cException memperluas pengecualian {public cException (string msg) {super (msg); }}Tiga kelas pengecualian Axception, Bexception, dan CException dibuat, maka Axception dilemparkan ke dalam (), Aecception ditangkap dalam B () dan Bexception dilemparkan, dan akhirnya Bexception terperangkap dalam C () dan CException dilemparkan, dan hasilnya dicetak sebagai berikut:
CException: Ini adalah pengecualian C di TestException.c (TestException.java:31) di TestException.main (testException.java:8)
OK, kami hanya melihat informasi CException, AException dan Bexception telah hilang, dan fungsi rantai pengecualian akan keluar, lihat kode:
Public Class TestException {public static void main (string [] args) {testException testException = testException baru (); coba {testException.c (); } catch (cException e) {e.printstacktrace (); }} public void a () melempar AException {aException aexception = AException baru ("Ini adalah pengecualian"); Lempar Aeksepsi; } public void b () melempar Bexception {coba {a (); } catch (aException e) {// lempar bexception baru ("Ini b exception"); Bexception bexception = new bexception ("Ini b Pengecualian"); bexception.initCause (e); Lempar Bexception; }} public void c () melempar cException {coba {b (); } catch (bexception e) {// lempar cException baru ("This is C Exception"); CException CException = CException baru ("Ini adalah CECECTION C"); cexception.initCause (e); melempar cexception; }}} kelas AException memperluas pengecualian {public aexception (string msg) {super (msg); }} kelas bexception memperluas pengecualian {public bexception (string msg) {super (msg); }} kelas cException memperluas pengecualian {public cException (string msg) {super (msg); }}Kami menggunakan metode initCause () untuk menghubungkan informasi pengecualian, dan hasilnya adalah sebagai berikut:
CException: this is c exception at TestException.c(TestException.java:35) at TestException.main(TestException.java:8) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.delegatingmethodaccessorImpl.invoke (delegatingmethodacessorimpl.java:43) di java.lang.reflect.method.invoke (Method.java:606) di com.intellij.rt.execution.application.appmain Ini adalah pengecualian di testException.b (testException.java:24) di testException.c (testException.java:32) ... 6 lebih banyak lagi oleh: AException: Ini adalah pengecualian di testException.a (testException.java:15) di testException.b (test exception.2) di test exception.b (exception.aPEpception.
Lima Postscript
Faktanya, masih ada banyak hal untuk dibahas tentang penanganan pengecualian Java, tetapi karena saya memiliki pengalaman yang terbatas, saya tidak dapat memahaminya terlalu dalam, dan yang paling umum digunakan adalah
Coba {...} catch (Exception e) {...} akhirnya {// kode yang akan dieksekusi terlepas dari apakah pengecualian akan ditangkap atau diproses, seperti menutup operasi IO}Tapi apa pun yang terjadi, kita masih harus berterima kasih kepada Java karena telah memberi kita mekanisme pengecualian. Ini seperti seorang penatua, membimbing kami dari waktu ke waktu, dan membuat kami kurang bosan saat pengkodean :)