犯這種錯誤的人比較少,通常發生在剛學會 Java 或者剛參加工做不久的人身上。
所謂「空 catch 語句塊」就是在 catch 語句塊中沒有對異常做任何處理(好比記錯誤日誌),致使異常信息被丟棄/忽略。一旦程序不能正確運行,因爲查不到任何 log 信息,只好從頭看代碼,靠肉眼找 bug。
函數
不少人在 catch 語句以後不使用 finally 語句。因爲在 try 語句中可能會涉及資源的申請和釋放。若是在資源申請以後、資源釋放以前拋出異常,就會發生資源泄露。
設計
有些人爲了省事,只在本身模塊的最外層代碼包一個 try 語句塊,而後 catch(Exception)。無論捕獲到什麼異常,都做統一 log 了事。這種作法比「空 catch 語句塊」稍好,但因爲不能對具體的異常進行具體處理,對一些可恢復的異常(下面會提到),喪失了恢復的機會。並且也可能致使上述提到的資源泄露的問題。
日誌
有些人放着 Java 的異常機制不用,而用函數返回值來表示成功/失敗(好比:返回 true 表示成功、false 表示失敗),簡直是「捧着金碗要飯」。我的感受,從 C 轉到 Java 的人比較容易有此毛病。這種作法會致使以下幾個問題:
1. 返回值通常用整數值或布爾值表示,傳遞的信息過於簡陋;
2. 一旦調用者忽略了錯誤返回碼,就會致使和「空 catch 語句塊」相似的問題;
2. 對同一個函數的多處調用,都須要對返回值進行重複判斷,致使代碼冗餘。
資源
這個現象比較廣泛,俺發現不少2年以上 Java 工做經驗的人還沒有徹底搞明白二者的區別。看來這個問題得詳細說一下。
當初Java的設計者有意區分這兩種異常,是別有深意的。其中「Checked Exception」用於表示可恢復的異常(也就是你必須檢查的異常);而「Runtime Exception」表示不可恢復的異常(也就是運行時異常,主要是程序 bug 和致命錯誤,你【不須要】檢查)。不過這種作法引來了不少爭議(包括不少 Java 大牛),鑑於本帖子主要針對新手,之後再專門來聊這個爭議的話題。
爲了便於理解,下面我舉一個例子來講明。假設你要寫一個 Download 函數,根據傳入的 URL(String 參數)返回對應網頁的內容文本。這時候有兩種狀況你須要處理:
1. 若是傳入的 URL 參數是 null,這代表該函數的調用者出 bug 了,而程序自己的 bug 是很難在運行時自我恢復的。這時候 Download 函數必須拋出 Runtime Exception。而且 Download 函數的調用者【不該該】嘗試去處理這個異常,必須讓它【儘早】暴露出來(好比讓 JVM 本身終止運行)。
2. 若是傳入的 URL 參數非 null,可是它包含的字符串不是一個合法的URL格式(可能因爲用戶輸入錯誤致使)。這時候 Download 函數必須拋出 Checked Exception。而且 Download 函數的調用者必須捕獲該異常並進行相應的處理(好比提示用戶從新輸入 URL)。字符串