但這不是那么簡單–受檢查的異常使代碼變得“丑陋”。 它們迫使開發人員編寫try / catch塊或重新拋出異常。 但是重新拋出隱藏了另一個問題–一些異常不應跨越模塊邊界。 當您不知道要做什么時,被迫捕獲一個已檢查的異常時,最常見的做法是將其包裝在RuntimeException中并重新拋出。
實際上,這可能不是最常見的-尤其是新手程序員傾向于吞下帶有空catch塊的異常。 如果存在一些用于異常處理的常規層,則日志和重新拋出有時會導致堆棧跟蹤加倍。 無論如何,這里有多種不良做法,導致難以調試和維護的代碼。
有人說,鑒于檢查過的異常所帶來的冗長,繁瑣和容易出錯,應該徹底消除它們。 C#根本沒有檢查過的異常。 當然,消除它們應該考慮向后兼容性。
但是,我認為擁有這兩種例外的決定具有其優點。 它迫使開發人員認為在這種情況下可能會發生異常,因此他必須采取措施。 API聲明它將拋出異常,并且開發人員將看到此編譯時 。 它增強了編譯時的安全性。 您不應該等到代碼投入生產后才發現可能會失敗。 Javadoc? 好吧,這是一個不錯的選擇,但是我敢打賭,直到異常發生之前,沒有人會閱讀javadoc。
那么,如何擁有“兩全其美”呢? 我有一個奇怪的想法( 請在此處詳細說明 ),使API定義兩個接口(通過繼承鏈接,因此實際上僅支持一個接口),并提供一種通過工廠獲得方法的方法,該實現的方法被檢查異常,或將檢查的異常包裝為未檢查的異常。 我不知道這可能是可行的,也可能是愚蠢的。 現在,它看起來很奇怪。
但是以上只是一個解決方法。 然后另一個想法來了–在方法上引入@RethrowExceptions
批注。 它會告訴編譯器,在此方法中,您不想處理已檢查的異常,但也不想聲明將其拋出。 (注釋的名稱可以改進)。 在我想到的最簡單的實現中,這可以簡單地告訴編譯器使用try {..} catch (Exception ex) { throw new RuntimeException(ex);}
包圍整個方法主體。 好處:
- 編譯器仍然警告您使用的方法可能會引發異常,因此您必須考慮處理它
- 通過不必要的嘗試/捕獲,您不會使代碼變得丑陋。 而且您不會強迫呼叫者考慮如何處理例外情況
- 吞下異常的可能性降低了。
簡而言之,這樣的注釋會將方法標記為無法處理異常并且不希望將此決定傳播給調用者的方法。
這個想法聽起來不那么奇怪。 我猜它現在甚至可以使用編譯器插件來實現。 還是已經在lombok項目中實現了?
別忘了分享!
參考: Bozho的技術博客博客中的JCG合作伙伴 Bozhidar Bozhanov提供的 Java中的Checked和Unchecked異常 。
翻譯自: https://www.javacodegeeks.com/2012/09/checked-and-unchecked-exceptions-in-java.html