Mari kita pertimbangkan situasi di mana Anda memiliki kode yang disediakan:
public void delete() throws IOException, SQLException { // Non-Compliant
/* ... */
}
Bahayanya di sini adalah bahwa kode yang Anda tulis untuk dihubungi delete()
akan terlihat seperti:
try {
foo.delete()
} catch (Exception e) {
/* ... */
}
Ini juga buruk. Dan itu akan ditangkap dengan aturan lain bahwa bendera menangkap kelas Exception dasar.
Kuncinya adalah untuk tidak menulis kode yang membuat Anda ingin menulis kode yang buruk di tempat lain.
Aturan yang Anda temui adalah aturan yang agak umum. Checkstyle memilikinya dalam aturan desainnya:
JumlahKuningan
Membatasi melempar pernyataan ke hitungan yang ditentukan (1 secara default).
Dasar Pemikiran: Pengecualian merupakan bagian dari antarmuka metode. Mendeklarasikan metode untuk melempar terlalu banyak pengecualian yang berakar berbeda membuat penanganan perkecualian berat dan mengarah pada praktik pemrograman yang buruk seperti menulis kode seperti catch (Exception ex). Pemeriksaan ini memaksa pengembang untuk menempatkan pengecualian ke dalam hierarki sehingga dalam kasus yang paling sederhana, hanya satu jenis pengecualian yang perlu diperiksa oleh penelepon tetapi setiap subclass dapat ditangkap secara khusus jika perlu.
Ini persis menggambarkan masalah dan apa masalahnya dan mengapa Anda tidak harus melakukannya. Ini adalah standar yang diterima dengan baik bahwa banyak alat analisis statis akan mengidentifikasi dan menandai.
Dan sementara Anda dapat melakukannya sesuai dengan desain bahasa, dan mungkin ada saat-saat itu adalah hal yang benar untuk dilakukan, itu adalah sesuatu yang harus Anda lihat dan segera lanjutkan "um, mengapa saya melakukan ini?" Mungkin dapat diterima untuk kode internal di mana setiap orang cukup disiplin untuk tidak pernah catch (Exception e) {}
, tetapi lebih sering daripada tidak saya pernah melihat orang mengambil jalan pintas terutama dalam situasi internal.
Jangan membuat orang menggunakan kelas Anda ingin menulis kode yang buruk.
Saya harus menunjukkan bahwa pentingnya ini dikurangi dengan Java SE 7 dan kemudian karena pernyataan tangkap tunggal dapat menangkap beberapa pengecualian ( Menangkap Beberapa Jenis Pengecualian dan Memotong Kembali Pengecualian dengan Memeriksa Jenis yang Ditingkatkan dari Oracle).
Dengan Java 6 dan sebelumnya, Anda akan memiliki kode yang terlihat seperti:
public void delete() throws IOException, SQLException {
/* ... */
}
dan
try {
foo.delete()
} catch (IOException ex) {
logger.log(ex);
throw ex;
} catch (SQLException ex) {
logger.log(ex);
throw ex;
}
atau
try {
foo.delete()
} catch (Exception ex) {
logger.log(ex);
throw ex;
}
Tak satu pun dari opsi ini dengan Java 6 yang ideal. Pendekatan pertama melanggar KERING . Beberapa blok melakukan hal yang sama, berulang-ulang - satu kali untuk setiap pengecualian. Anda ingin mencatat pengecualian dan melakukan rethrow? Baik. Baris kode yang sama untuk setiap pengecualian.
Opsi kedua lebih buruk karena beberapa alasan. Pertama, itu berarti Anda menangkap semua pengecualian. Null pointer tertangkap di sana (dan seharusnya tidak). Selain itu, Anda rethrowing sebuah Exception
yang berarti bahwa metode tanda tangan akan deleteSomething() throws Exception
yang hanya membuat berantakan lebih jauh stack sebagai orang yang menggunakan kode Anda sekarang dipaksa untuk catch(Exception e)
.
Dengan Java 7, ini tidak seperti yang penting karena Anda malah dapat melakukan:
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
Selanjutnya, jenis memeriksa jika salah satu tidak menangkap jenis pengecualian yang dilemparkan:
public void rethrowException(String exceptionName)
throws IOException, SQLException {
try {
foo.delete();
} catch (Exception e) {
throw e;
}
}
Pemeriksa tipe akan mengenali bahwa e
mungkin hanya tipe IOException
atau SQLException
. Saya masih tidak terlalu antusias tentang penggunaan gaya ini, tapi itu tidak menyebabkan kode seburuk di bawah Java 6 (di mana itu akan memaksa Anda untuk memiliki metode tanda tangan menjadi superclass yang pengecualiannya diperluas).
Terlepas dari semua perubahan ini, banyak alat analisis statis (Sonar, PMD, Checkstyle) masih menerapkan panduan gaya Java 6. Itu bukan hal yang buruk. Saya cenderung setuju dengan peringatan ini agar tetap diberlakukan, tetapi Anda dapat mengubah prioritasnya menjadi mayor atau minor sesuai dengan cara tim Anda memprioritaskannya.
Jika pengecualian harus diperiksa atau dicentang ... yang adalah masalah g r e a t debat yang satu dapat dengan mudah menemukan posting blog yang tak terhitung jumlahnya mengambil setiap sisi argumen. Namun, jika Anda bekerja dengan pengecualian yang diperiksa, Anda mungkin harus menghindari melempar beberapa jenis, setidaknya di bawah Java 6.