Apakah Praktik yang Buruk Menangkap Dapat Dilempar?

1. Ikhtisar

Dalam tutorial ini, kita akan melihat implikasi dari menangkap Throwable .

2. Kelas Throwable

Dalam dokumentasi Java, kelas Throwable didefinisikan sebagai " kelas super dari semua kesalahan dan pengecualian dalam bahasa Java ".

Mari kita lihat hierarki kelas Throwable :

Kelas Throwable memiliki dua sub-kelas langsung - yaitu kelas Error dan Exception .

Kesalahan dan sub-kelasnya adalah pengecualian yang tidak dicentang, sedangkan sub-kelas Pengecualian dapat dicentang atau pengecualian yang tidak dicentang.

Mari kita lihat jenis situasi yang dapat dialami program ketika gagal.

3. Situasi yang Dapat Dipulihkan

Ada situasi di mana pemulihan secara umum dimungkinkan dan dapat ditangani dengan sub-kelas kelas Exception yang dicentang atau tidak dicentang .

Misalnya, program mungkin ingin menggunakan file yang kebetulan tidak ada di lokasi yang ditentukan, sehingga FileNotFoundException yang dicentang dilempar.

Contoh lainnya adalah program yang mencoba mengakses sumber daya sistem tanpa izin untuk melakukannya, mengakibatkan Pengecualian AccessControl yang tidak dicentang dilempar.

Sesuai dokumentasi Java, yang Exception kelas “menunjukkan kondisi yang aplikasi yang wajar mungkin ingin menangkap ”.

4. Situasi yang Tidak Bisa Dipulihkan

Ada kasus di mana program bisa berada dalam keadaan di mana pemulihan tidak mungkin terjadi jika terjadi kegagalan. Contoh umum dari hal ini adalah ketika terjadi stack overflow atau JVM kehabisan memori.

Dalam situasi ini, JVM menampilkan StackOverflowError dan OutOfMemoryError , masing-masing. Seperti yang disarankan oleh namanya, ini adalah sub-kelas dari kelas Error .

Menurut dokumentasi Java, yang Kesalahan kelas “menunjukkan masalah serius bahwa aplikasi yang wajar tidak harus mencoba untuk menangkap ”.

5. Contoh Situasi yang Dapat Dipulihkan dan Tidak Dapat Dipulihkan

Mari kita asumsikan bahwa kita memiliki API yang memungkinkan pemanggil menambahkan ID unik ke beberapa fasilitas penyimpanan menggunakan metode addIDsToStorage :

class StorageAPI { public void addIDsToStorage(int capacity, Set storage) throws CapacityException { if (capacity < 1) { throw new CapacityException("Capacity of less than 1 is not allowed"); } int count = 0; while (count < capacity) { storage.add(UUID.randomUUID().toString()); count++; } } // other methods go here ... }

Beberapa potensi titik kegagalan dapat terjadi saat menjalankan addIDsToStorage :

  • CapacityException - Subkelas Exception yang dicentang saat meneruskan nilai kapasitas kurang dari 1
  • NullPointerException - Sub-kelas Exception yang tidak dicentang jika nilai penyimpanan null disediakan alih-alih instance Set
  • OutOfMemoryError - Sub-kelas Error yang tidak dicentang jika JVM kehabisan memori sebelum keluar dari while loop

Situasi CapacityException dan NullPointerException adalah kegagalan yang dapat dipulihkan oleh program, tetapi OutOfMemoryError tidak dapat dipulihkan.

6. Catching Throwable

Mari asumsikan bahwa pengguna API hanya menangkap Throwable di try-catch saat memanggil addIDsToStorage :

public void add(StorageAPI api, int capacity, Set storage) { try { api.addIDsToStorage(capacity, storage); } catch (Throwable throwable) { // do something here } }

Ini berarti kode panggilan bereaksi terhadap situasi yang dapat dipulihkan dan tidak dapat dipulihkan dengan cara yang sama.

Aturan umum dalam menangani pengecualian adalah bahwa blok coba-tangkap harus sespesifik mungkin dalam menangkap pengecualian. Artinya, skenario penampung-semua harus dihindari .

Catching Throwable dalam kasus kami melanggar aturan umum ini. Untuk bereaksi terhadap situasi yang dapat dipulihkan dan tidak dapat dipulihkan secara terpisah, kode panggilan harus memeriksa instance objek Throwable di dalam blok catch .

Cara yang lebih baik adalah menggunakan pendekatan khusus dalam menangani pengecualian dan menghindari mencoba menangani situasi yang tidak dapat dipulihkan .

7. Kesimpulan

Dalam artikel ini, kami melihat implikasi dari menangkap Throwable dalam blok coba-tangkap .

Seperti biasa, kode sumber lengkap dari contoh ini tersedia di Github.