Alasan mengapa pengecualian adalah metode debugging yang kuat adalah karena mereka menjawab tiga pertanyaan berikut:
1. Apa yang salah?
2. Di mana Anda melakukan kesalahan?
3. Mengapa ada yang salah?
Dalam hal penggunaan pengecualian yang efektif, tipe pengecualian menjawab "apa" yang dilemparkan, pengecualian menumpuk jawaban "di mana" dilemparkan, informasi pengecualian menjawab "mengapa" dilemparkan, dan jika pengecualian Anda tidak menjawab semua pertanyaan di atas, maka Anda tidak boleh menggunakannya dengan baik.
Ada tiga prinsip yang dapat membantu Anda memaksimalkan penggunaan pengecualian yang baik selama debugging. Ketiga prinsip ini adalah:
1. Khusus dan jelas
2. Lempar lebih awal
3. Penangkapan penundaan
Untuk menjelaskan ketiga prinsip penanganan pengecualian yang efektif ini, artikel ini membahasnya dengan membuat buku JCHECK BUKU JCHECK, yang digunakan untuk merekam dan melacak kegiatan rekening bank seperti deposito dan penarikan dan penerbitan RUU.
Beton dan jelas
Java mendefinisikan hierarki kelas pengecualian, yang dimulai dengan Throwable, memperluas kesalahan dan pengecualian, dan pengecualian memperluas runtimeException. Seperti yang ditunjukkan pada Gambar 1.
Keempat kelas ini digeneralisasi dan tidak memberikan banyak informasi kesalahan. Meskipun instantiating kelas -kelas ini secara legal secara sintaksis (seperti: New Throwable ()), yang terbaik adalah memperlakukan mereka sebagai kelas dasar virtual dan menggunakan subclass yang lebih khusus. Java telah menyediakan sejumlah besar subkelas pengecualian. Jika Anda ingin lebih spesifik, Anda juga dapat menentukan kelas pengecualian Anda sendiri.
Sebagai contoh: Paket Java.io mendefinisikan subkelas kelas pengecualian IOException, yang lebih khusus dan subkelas IOException seperti FileNotFoundException, EOFException dan ObjectStreamException. Masing -masing menggambarkan kelas tertentu dari kesalahan I/O: kehilangan file, ujung file pengecualian dan aliran objek serial kesalahan. Semakin spesifik pengecualian, program kami akan dapat menjawab pertanyaan "apa yang salah".
Penting juga untuk mencoba sejelas mungkin saat menangkap pengecualian. Misalnya: JCheckBook dapat menangani FileNotFoundException dengan memesan kembali nama file pengguna. Untuk eofexception, dapat terus berjalan berdasarkan informasi yang dibaca sebelum pengecualian dilemparkan. Jika ObjectStreamException dilemparkan, program harus meminta pengguna bahwa file tersebut rusak dan file cadangan atau file lain harus digunakan.
Java memudahkan untuk menangkap pengecualian secara eksplisit, karena kita dapat mendefinisikan beberapa blok tangkapan untuk blok percobaan yang sama, sehingga setiap pengecualian dapat ditangani secara tepat secara terpisah.
File prefsfile = file baru (prefsfileName); coba {readPreferences (prefsfile);} catch (filenotfoundException e) {// waspada pengguna bahwa file yang ditentukan // tidak ada} catch (eofexception e) {// peringatkan pengguna bahwa akhir file // dicapai} Corrome (objeksepsi e) { / / wear dari file // dicapai {ObjectStreamException e) { / / wear dari pengguna // dicapai bahwa beberapa kesalahan I/O // terjadi kesalahan}JCheckBook memberikan informasi eksplisit kepada pengguna tentang penangkapan pengecualian dengan menggunakan beberapa blok tangkapan. Misalnya: Jika FileNotFoundException ditangkap, itu dapat meminta pengguna untuk menentukan file lain. Dalam beberapa kasus, upaya pengkodean tambahan yang dibawa oleh beberapa blok tangkapan mungkin merupakan beban yang tidak penting, tetapi dalam contoh ini, kode tambahan memang membantu program memberikan respons yang lebih ramah pengguna.
Selain pengecualian yang ditangani oleh tiga blok tangkapan pertama, blok tangkapan terakhir memberi pengguna informasi kesalahan yang lebih umum ketika IOException dilemparkan. Dengan cara ini, program ini dapat memberikan informasi spesifik sebanyak mungkin, tetapi juga memiliki kemampuan untuk menangani pengecualian yang tidak terduga lainnya.
Terkadang pengembang menangkap pengecualian yang dinormalisasi dan menampilkan nama kelas pengecualian atau informasi cetak tumpukan untuk "spesifisitas". Jangan lakukan ini! Pengguna hanya akan sakit kepala saat melihat java.io.EOFException atau menumpuk informasi, daripada mendapatkan bantuan. Pengecualian khusus harus ditangkap dan pengguna harus diminta dengan "kata -kata manusia". Namun, tumpukan pengecualian dapat dicetak dalam file log Anda. Ingat, pengecualian dan informasi tumpukan digunakan untuk membantu pengembang daripada pengguna.
Akhirnya, perlu dicatat bahwa JCheckbook tidak menangkap pengecualian di readPreferences() , tetapi meninggalkan tangkapan dan menangani pengecualian ke lapisan antarmuka pengguna, sehingga pengguna dapat diberitahu menggunakan kotak dialog atau metode lain. Ini disebut "penangkapan penundaan", yang akan dibahas di bawah ini.
Buang lebih awal
Informasi tumpukan pengecualian memberikan urutan yang tepat dari rantai panggilan metode yang menyebabkan pengecualian terjadi, termasuk nama kelas, nama metode, nama file kode dan bahkan nomor baris dari setiap panggilan metode, untuk secara akurat menemukan pemandangan di mana pengecualian terjadi.
java.lang.nullpointerExceptionat java.io.fileInputStream.open (metode asli) di java.io.fileInputStream. <inin> (FileInputStream.java:103) di jcheckbook.jcheckbook.readpreferences (jcheckbook.java:25) at jcheckbook.jcheckbook.startup (jcheckbook.java:116) di jcheckbook.jcheckbook. <inin> (jcheckbook.java:27) di jcheckbook.jcheckbook.main (jcheckbook.java:318)
Di atas menunjukkan kasus di mana metode open () dari kelas fileInputStream melempar nullpointerException. Namun, perhatikan bahwa FileInputStream.close() adalah bagian dari pustaka kelas Java standar, dan kemungkinan masalah pengecualian ini adalah bahwa kode kita sendiri bukan Java API. Jadi masalahnya kemungkinan akan muncul dalam salah satu metode sebelumnya, dan untungnya juga dicetak dalam informasi tumpukan.
Sayangnya, NullpointerException adalah pengecualian paling tidak informatif (tetapi juga yang paling umum dan menabrak) di Java. Tidak menyebutkan apa yang paling kita pedulikan: di mana null. Jadi kami harus mengambil beberapa langkah ke belakang dan mencari tahu di mana terjadi kesalahan.
Secara langkah mendukung informasi tumpukan pelacakan dan memeriksa kode, kami dapat menentukan bahwa penyebab kesalahannya adalah bahwa parameter nama file kosong diteruskan ke readPreferences() . Karena readPreferences() tahu bahwa itu tidak dapat menangani nama file kosong, periksa kondisinya segera:
public void readPreferences (string filename) melempar illegalArgumentException {if (fileName == null) {lempar baru ilegalargumentException ("fileName is null"); } // if //...perform operasi lain ... inputStream in = new FileInputStream (fileName); //... Baca file preferensi ...} Dengan melempar pengecualian lebih awal (juga dikenal sebagai "kegagalan dengan cepat"), pengecualiannya jelas dan akurat. Informasi tumpukan segera mencerminkan apa yang salah (nilai parameter ilegal disediakan), mengapa itu salah (nama file tidak bisa nol), dan di mana itu salah (bagian pertama readPreferences() ). Dengan cara ini, informasi tumpukan kami dapat disediakan dengan jujur:
java.lang.illegalargumentException: nama file adalah nullat jcheckbook.jcheckbook.readpreferences (jcheckbook.java:207) di jcheckbook.jcheckbook.startup (jcheckbook.java:116) di jcheckbook.jchchbook. jcheckbook.jcheckbook.main (jcheckbook.java:318)
Selain itu, informasi pengecualian yang terkandung di dalamnya ("Nama file kosong") membuat pengecualian lebih kaya dengan secara eksplisit menjawab pertanyaan tentang apa yang kosong, yang tidak tersedia bagi kami dalam kode sebelumnya.
Kegagalan dicapai dengan melemparkan pengecualian segera ketika kesalahan terdeteksi, konstruksi objek yang tidak perlu atau penggunaan sumber daya, seperti file atau koneksi jaringan, dapat dihindari secara efektif. Demikian pula, operasi pembersihan yang disebabkan dengan membuka sumber daya ini dapat disimpan.
Penangkapan tertunda
Salah satu kesalahan yang dapat dilakukan oleh baik pemula dan tuan adalah menangkap program sebelum memiliki kemampuan untuk menangani pengecualian. Kompiler Java secara tidak langsung memfasilitasi perilaku ini dengan mensyaratkan bahwa pengecualian yang diperiksa harus ditangkap atau dilemparkan. Cara alami adalah dengan segera membungkus kode dalam blok mencoba dan menggunakan tangkapan untuk menangkap pengecualian untuk menghindari kesalahan kompiler.
Pertanyaannya adalah, apa yang harus saya lakukan jika saya mendapatkan pengecualian setelah ditangkap? Hal terburuk yang harus dilakukan adalah tidak melakukan apa pun. Blok tangkapan kosong setara dengan melemparkan seluruh pengecualian ke dalam lubang hitam, dan semua informasi yang dapat menjelaskan kapan, di mana, mengapa kesalahan salah akan hilang selamanya. Sedikit lebih baik untuk menulis pengecualian ke dalam log, setidaknya ada catatan untuk diperiksa. Tetapi kami tidak dapat mengharapkan pengguna untuk membaca atau memahami file log dan informasi pengecualian. Juga tidak tepat untuk memiliki readPreferences() menampilkan dialog pesan kesalahan, karena sementara JCheckBook saat ini merupakan aplikasi desktop, kami juga berencana untuk mengubahnya menjadi aplikasi web berbasis HTML. Dalam hal ini, menampilkan dialog kesalahan jelas bukan opsi. Pada saat yang sama, terlepas dari versi HTML atau C/S, informasi konfigurasi dibaca di server, dan pesan kesalahan perlu ditampilkan ke browser web atau program klien. readPreferences() juga harus mempertimbangkan kebutuhan masa depan ini saat merancang. Pemisahan kode antarmuka pengguna dan logika program yang tepat dapat meningkatkan penggunaan kembali kode kami.
Menangkap pengecualian sebelum waktunya sebelum penanganan bersyarat sering menghasilkan kesalahan yang lebih serius dan pengecualian lainnya. Misalnya, jika metode readPreferences() di atas segera menangkap dan mencatat fileNoTFoundException yang dapat dilemparkan ketika konstruktor FileInputStream dipanggil, kode akan menjadi seperti ini:
public void readPreferences (string fileName) {// ... inputStream in = null; // Jangan lakukan ini !!! coba {in = new FileInputStream (fileName);} catch (filenotfoundException e) {logger.log (e);} in.read (...); // ...}Kode di atas menangkapnya tanpa kemampuan untuk memulihkan dari FileNotFoundException. Jika file tidak dapat ditemukan, metode berikut jelas tidak dapat membacanya. Apa yang terjadi jika ReadPreferences () diminta untuk membaca file yang tidak ada? Tentu saja, FileNotFoundException akan direkam, dan jika kami melihat file log pada waktu itu, kami akan tahu. Namun, apa yang terjadi ketika suatu program mencoba membaca data dari file? Karena file tidak ada, variabel dalam kosong, dan nullpointerException akan dilemparkan.
Saat men -debug suatu program, Insting memberitahu kita untuk melihat informasi di akhir log. Itu akan menjadi NullpointerException, dan yang sangat menjengkelkan adalah bahwa pengecualian ini sangat tidak spesifik. Pesan kesalahan tidak hanya menyesatkan kami apa yang salah (kesalahan nyata adalah filenotfoundException alih -alih nullpointerexception), tetapi juga menyesatkan sumber kesalahan tersebut. Masalah sebenarnya adalah di luar jumlah baris di NullpointerException yang dilemparkan, yang mungkin memiliki beberapa panggilan metode dan penghancuran kelas. Perhatian kami terkandung dari kesalahan nyata oleh ikan kecil sampai kami melihat kembali log untuk menemukan sumber masalahnya.
Karena apa yang sebenarnya harus dilakukan readPreferences() adalah tidak menangkap pengecualian ini, apa yang seharusnya? Tampaknya agak berlawanan dengan intuisi, dan cara yang paling tepat adalah tidak melakukan apa pun dan tidak segera menangkap pengecualian. Serahkan tanggung jawab kepada penelepon readPreferences() dan biarkan mempelajari cara yang tepat untuk menangani file konfigurasi yang hilang. Ini dapat meminta pengguna untuk menentukan file lain, atau menggunakan nilai default. Jika benar -benar tidak berhasil, itu mungkin memperingatkan pengguna dan keluar dari program.
Cara untuk lulus tanggung jawab untuk pengecualian penanganan hulu dari rantai panggilan adalah dengan menyatakan pengecualian dalam klausa lemparan metode. Saat menyatakan kemungkinan pengecualian, hati -hati, semakin spesifik semakin baik. Ini digunakan untuk mengidentifikasi jenis pengecualian yang perlu diketahui oleh program yang memanggil metode Anda dan siap untuk ditangani. Misalnya, versi "Delay Capture" dari readPreferences() mungkin terlihat seperti ini:
public void readPreferences (string filename) melempar ilegalargumentException, filenotfoundException, ioException {if (fileName == null) {lempar baru ilegalargumentException ("nama file is null"); } // if // ... inputStream in = new fileInputStream (nama file); // ...}Secara teknis, satu -satunya pengecualian yang perlu kami nyatakan adalah iOException, tetapi kami secara eksplisit menyatakan bahwa metode tersebut dapat melempar file fileNoTFoundException. IllegalargumentException tidak perlu dinyatakan karena itu adalah pengecualian yang tidak memeriksa (mis., Subkelas RuntimeException). Namun, dinyatakan untuk mendokumentasikan kode kami (pengecualian ini juga harus ditandai dalam Javadocs dari metode ini).
Tentu saja, pada akhirnya program Anda perlu menangkap pengecualian, jika tidak maka akan berakhir secara tidak terduga. Tetapi triknya di sini adalah menangkap pengecualian di tingkat yang tepat sehingga program Anda dapat memulihkan secara bermakna dari pengecualian dan berlanjut tanpa menyebabkan kesalahan yang lebih dalam; Atau dapat memberikan pengguna informasi yang jelas, termasuk membimbing mereka untuk pulih dari kesalahan. Jika metode Anda tidak kompeten, maka jangan menangani pengecualian, tinggalkan untuk menangkap dan menanganinya di level yang tepat.
Meringkaskan
Pengembang yang berpengalaman tahu bahwa kesulitan terbesar dalam debugging program adalah bukan untuk memperbaiki cacat, tetapi untuk mengetahui tempat persembunyian cacat dari sejumlah besar kode. Selama Anda mengikuti tiga prinsip artikel ini, pengecualian Anda dapat membantu Anda melacak dan menghilangkan cacat, membuat program Anda lebih kuat dan ramah pengguna. Di atas adalah seluruh konten artikel ini, dan saya harap ini akan membantu Anda dalam studi atau pekerjaan Anda.