84669 人學習
152542 人學習
20005 人學習
5487 人學習
7821 人學習
359900 人學習
3350 人學習
180660 人學習
48569 人學習
18603 人學習
40936 人學習
1549 人學習
1183 人學習
32909 人學習
使用 Error、RuntimeException、Throwable 和 Exception 等通用異常可防止呼叫方法以不同於應用程式產生的錯誤的方式處理真正的、系統產生的例外。
這個很容易理解啊.打個簡單的比方. 現在做一個登錄有用戶不存在/密碼錯誤... 這些錯誤類型, 如果你直接使用RuntimeException 代碼要寫成這樣.
用戶不存在/密碼錯誤...
RuntimeException
throw new RuntimeException("user not found"); // 用户不存在 throw new RuntimeException("password not match"); // 密码错误
捕捉異常
try { // ...逻辑 } catch(RuntimeException e) { if("user not found".equals(e.getMessage())) { // ...逻辑 } else if("password not match".equals(e.getMessage())) { // ...逻辑 } }
反之自訂異常實作如下:
throw new UserNotFoundException("user not found"); // 用户不存在 throw new PasswordNotMatchException("password not match"); // 密码错误
try { // ...逻辑 } catch(UserNotFoundException e) { // ...逻辑 } catch(PasswordNotMatchException e) { // ...逻辑 }
透過message判斷處理異常邏輯有很多弊端, 例如message是動態的, 那將無法準確的處理.當然我們也可以定義一個通用的異常類型, 通過業務碼去判斷會更加準確, 同時也會減少異常類型的定義, 減少程式碼的冗餘. 下面有一段kotlin程式碼, 目前我是使用的這種處理方式.
message
kotlin
interface BizCode { val code: Int val msg: String } enum class BizCodes(override val code: Int, override val msg: String): BizCode { // ====================================================== // // 公共错误码 0 - 999 // // ====================================================== // /** * 未知错误. */ C_0(0, "未知错误"), /** * HTTP Request 参数错误. */ C_999(999, "HTTP Request 参数错误"), // ====================================================== // // client 错误码 1000 - 1999 // // ====================================================== // /** * 未发现指定 client_id 客户端记录. */ C_1000(1000, "未发现指定 client_id 客户端记录"), C_1001(1001, "client_secret 不匹配"), // ====================================================== // // user 错误码 2000 - 2999 // // ====================================================== // /** * 未发现指定 email 的用户. */ C_2000(2000, "未发现指定 email 的用户"), C_2011(2011, "password 不匹配"), // ; override fun toString(): String { return "[$code] $msg" } } class BizCodeException : RuntimeException { val bizCode: BizCode constructor(bizCode: BizCode) : super(bizCode.toString()) { this.bizCode = bizCode } constructor(bizCode: BizCode, e: Exception) : super(bizCode.toString(), e) { this.bizCode = bizCode } override fun fillInStackTrace() = this }
說明的挺清楚了啊,方便捕獲處理
Exception名字要有意義,RuntimeException名字沒有意義
Exception直接拋的話,Nginx 會把你定義message 覆蓋掉,導致看不到具體資訊。 建議的做法是,自己定義一個exception,去繼承 RuntimeException,這個就知道你的exception 是什麼,也方便找出問題。
運作時異常不需要捕捉
這個很容易理解啊.
打個簡單的比方. 現在做一個登錄有
用戶不存在/密碼錯誤...
這些錯誤類型, 如果你直接使用RuntimeException
代碼要寫成這樣.捕捉異常
反之自訂異常實作如下:
捕捉異常
透過
message
判斷處理異常邏輯有很多弊端, 例如message
是動態的, 那將無法準確的處理.當然我們也可以定義一個通用的異常類型, 通過業務碼去判斷會更加準確, 同時也會減少異常類型的定義, 減少程式碼的冗餘. 下面有一段
kotlin
程式碼, 目前我是使用的這種處理方式.說明的挺清楚了啊,方便捕獲處理
Exception名字要有意義,RuntimeException名字沒有意義
Exception直接拋的話,Nginx 會把你定義message 覆蓋掉,導致看不到具體資訊。
建議的做法是,自己定義一個exception,去繼承 RuntimeException,這個就知道你的exception 是什麼,也方便找出問題。
運作時異常不需要捕捉