Exception
異常處理機制
Java Exception 異常處理機制其實起源很早,所以它也不是個什麼新鮮的東西,如果您對Exception機制一點都不了解,沒關係,只是國內通常接觸新事物的時間都相對的要晚老美幾年,但了解Java Exception機制對Java開發人員來說是必要的,不過Exception 異常處理機制也並沒有固定,在Anders 的眼裡它也是一個試驗性的東西。理論上異常處理劃分為兩個模型(中止模型與繼續模型),但實際使用方面我們對中止模型用的比較多,這個模型比較實用,而繼續模型則不是那麼的應用普遍,多少是耦合的過於緊密。
為什麼要自定義自己的Exception ,Java Exception機制與傳統的C語言的異常處理機制有什麼不同,這種Exception機制的意義在什麼地方?接下來咱就來和你一起探討Exception 的優缺點。
早期的C語言的異常處理機制,通常是我們人為的對返回結果加一些標誌來進行判定,比如發生錯誤返回什麼標誌,正常情況下我們又是返回什麼標記,而這些都不是語言本身所賦予我們的,而對於C語言這種機制又有什麼問題哩?為什麼新一代的語言 Java Ruby C# 等都用Exception機制而不是維持C語言的老樣子?這些都是我們需要思考的問題。
C語言的異常處理機制全是我們人為的定義,這樣就會造成業務邏輯的主線受到異常處理的牽制,或者說是我們難免會將注意力轉移,並且造成業務邏輯與異常處理之間有很大程度上的纏繞。
假設錯誤非常嚴重,已至你無法在回到錯誤發生的地方,也就是說,這段程序經過判斷認為,他已經沒有辦法挽回,於是就拋出異常,希望這個異常不要在回來,這也是Java 當前所採用的模式。
這種模型的主旨是恢復當前的運行環境,然後希望能夠重新回到錯誤的發生地,並希望第二次的嘗試能夠獲得成功,這種模型通常為操作系統所應用。
cap/cep/cip/ceive=to take 取,拿
來源於拉丁文capere,"take,seize"。captor(n.捕捉者,捕快)會capture(v.俘獲,捕獲)captive
(n.俘虜,被捕捉的人或動物);如果你的心被取走了,那叫做captive(v.迷惑,迷住);ex-外+cept取->
取出來->except除...之外;anti-之前+cip取+-ate動詞後綴->之前就取得了->anticipate 語氣,
預料
讓異常處理與業務邏輯的主線分離,我們可以對可以遇見的異常作分支處理,其實將業務邏輯與異常處理分離也是Exception設計的主旨,其次Java Exception 不需要像C語言那樣在程序的多個地方去檢測同一個錯誤,並就地作異常的處理,相比老式的錯誤處理,現行的錯誤處理的結構則來的更加清晰。
public class T {
UserManager manager = new UserManager();
public void testloadUser(String username, String password, String name, String email) {
try {
manager.loadUser(username);
}
catch (UserNotFoundException unfe) {
}
}
}
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class UserManager {
public User loadUser(String username) throws UserNotFoundException {
Connection con = null;
PreparedStatement pstmt = null;
try {
pstmt = con.prepareStatement("select User form user where id=1");
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();
if (!rs.next()) {
throw new UserNotFoundException();
}
return null;
} catch (SQLException ex) {
return null;
}
}
}
class User {
}
public class UserNotFoundException extends Exception {
private Throwable nestedThrowable = null;
public UserNotFoundException() {
super();
}
public UserNotFoundException(String msg) {
super(msg);
}
}
在這裡我們自定義了自己的UserNotFoundException異常,這樣在客戶調用loadUser()方法的時候Java就可以強制檢測到這個UserNotFoundException異常,這樣我們就可以作相應的處理工作,在這裡應該可以看到testloadUser這裡對UserNotFoundException這個異常有一個分支處理,這樣的異常分支處理是不是很清晰哩,在此我不對他作解釋,因為實在比較簡單,其實美好的東西在我看來都有一個度,當這個度被你所打破后,那麼他將不會再美好,Exception機制的應用也是,而這個度就需要你自己在實際項目中去斟酌了,接下來我就會闡述Exception的缺點。
Java 有將受控異常和運行時異常模型都實現,Rod Johnson認為在Java中主要實現運行時異常模型,至於受控異常則為輔,而Bruce Eckel則來的更為偏激一些,他認為Java只需要實現運行時異常模型,而受控異常沒有必要繼續存在,為什麼他們都這麼認為哩,而且Bruce Eckel 之前很是推崇受控異常地,其實也沒那麼多為什麼,這些思維的改變不過就是他們在實踐當中發現了很多問題且對Exception 認識也更深刻了唄,所以說大師不是天生的,大師也需要學習,在這裡我更贊成Rod Johnson 對Exception的觀點,OK,廢話我也不多說了,說說我認識中的Java Exception 缺點!
1 、當一個方法中被過多的拋出受控異常,那麼在別人調用的時候會造成try/catch語句的泛濫,甚至經常出現嵌套異常,使得代碼的可讀性下降。
2、在某些方面檢測系統的異常也並沒有實際的意義,因為當出現這種異常的時候一般代表問題很嚴重我們無法恢復,如:捕獲資料庫SQLException異常,該異常對我們來說沒太大意義,因為錯誤信息太模糊,通常都是一些堆棧上的信息,看Rod Johnson 設計的關於JDBC方面的Exception Framework相信會對您產生很大的觸動。
3、在大型系統中受控異常同時會造成異常處理類的泛濫,其實本人並沒有介入過什麼大型的Java 系統的設計工作,所以我也無從對這指三道四,沒有實踐就沒有發言權,但我在一般的系統已經多少看到了一些這樣的問題。
最後希望我的這篇解說能夠進一步的增加你對 Java Exception 機制的了解,如果您還是不太清楚Exception機制,那麼我推薦你看 《Thinking in Java》 這本書的第三版以及Rod Johnson的 expert one on one 系列書籍
建立Exception 時建議日常開發中需要注意以下幾點:
一、Throw new exception
曾經看過有人在簡單的函數內瘋狂的使用throw new 參與業務邏輯。比如,以下代碼:
邏輯類似以上代碼,就是一個單一的函數,每當我看到這樣的單一函數,總是覺得很奇怪。或許是自身水平有限,似乎難以理解為了catch住一個exception對象需要那麼大費周章的去throw new 么?個人認為如果某方法內嵌套的方法根據業務邏輯主動拋出異常,讓外層方法截獲到這個異常,此時被嵌套的方法方可使用throw new ....
二、拋出不該拋出的Exception
上文中的DoSomeThing函數如果在catch時不進一步封裝,直接把Excepiton拋到UI層,又或者直接顯示給客戶。如果異常堆棧中提示某些敏感數據。比如SQL查詢語句、WebService
URI或POST信息等。這些敏感信息應該永遠不讓客戶知道,暴露出這些信息有可能對系統造成潛在安全隱患!
類似以上機制,如果異常出現了,我認為可以大大減少debug的時間。