分享一個你很可能不知道的Java異常實現的缺陷

2022-12-07 12:00:48

前言

Java中一個大家熟知的知識點就是異常捕獲,try...catch...finally組合,但是很多人不知道這裡面有一個關於Java的缺陷,或者說是異常實現的一點不足之處。

我這邊就通過一個很簡單的實驗給大家演示下效果玩玩兒,希望大家能覺得有趣。

模擬

1、自定義異常

這裡,我們首先寫一個自定義業務異常,專門用來丟擲。

2、模擬異常

然後,我們寫個測試方法來捕獲並丟擲空指標異常。

看下效果,OK沒問題。

接下來,我們加上finally看看。

看下效果,OK也沒問題。

接下來我們這麼做,在finally中丟擲一個異常。

看下效果,發現catch的異常竟然被覆蓋了。

雖然這種場景很特殊,但這其實就是Java在異常實現上美中不足的地方,因為異常是作為程式出錯的標誌絕對不應忽略,可是這種場景下異常的的確確丟失了。

接下來,我們再測試一種情況,在finally中使用return,看看會發生什麼。

看看效果,發現catch中捕獲的異常乾脆直接沒了,彷彿從沒來過。

最後,我們再演示一種你可能工作中幹過或者見過的莫名其妙的事情。

我們修改一下這個測試方法,看程式碼。

簡單描述一下,你呼叫其他類的一個查詢方法,那個方法可能習慣性的try..catch..finally了,而finally中還做了一些末尾必須要執行的操作,這個業務邏輯處理可能有幾十行,你很可能又習慣性的做了一些判斷以及異常的丟擲。

別不相信,當一個專案進入中期甚至趕進度的時候,方法套方法,不少人已經在機械的茫然的寫程式碼,也可能是在別人的基礎上改程式碼,你很可能不會太仔細地一行一行去看那些程式碼裡究竟有什麼,恰巧測試的時候也沒出什麼大問題。

那麼結果可能就是下面這樣,你會發現自己一開始特意丟擲的那個捕獲該查詢方法異常的玩意兒沒一點效果,也不知道去哪兒了,怎麼找也找不到,不知從哪兒冒出來下面這個莫名其妙的異常,後來想不到也就算了。

原因

這其實就是Java異常實現的一個不足,異常是程式出錯的標誌,怎麼都不應該被忽略掉,更不用說是finally這種常用的行為,直接或間接地造成了異常的丟失。

《Thinking In Java》的作者有明確指出這個異常,認為這是相當嚴重的缺陷,是一個可能造成異常完全丟失的缺陷,而且是以一種更微妙、更難以察覺的方式在進行。

而C++就處理的很好,會將這種在第一個異常被處理之前丟擲第二個異常的情況視為嚴重的程式設計錯誤。

總結

知道了這個缺陷後,其實就很好避免了。

1、避免在finally中丟擲異常;

2、避免在finally中使用return;

3、catch中一定要養成log.error記錄異常紀錄檔的好習慣,因為log是一定會記錄下來的,至少不會讓你毫無線索。

結尾再演示下加了紀錄檔的效果,只要是catch我都加上紀錄檔,那麼一定不會錯過。


原創文章純手打,一個一個字敲出來的,鍵盤上全是血,如果覺得有幫助麻煩點個推薦吧~

本人致力於分享工作中的經驗及趣事,喜歡的話可以進主頁關注一下哦~