Using such generic exceptions as Error, RuntimeException, Throwable, and Exception prevents calling methods from handling true, system-generated exceptions differently than application-generated errors.
public void foo(String bar) throws Throwable { // Noncompliant
throw new RuntimeException("My Message"); // Noncompliant
}
public void foo(String bar) {
throw new MyOwnRuntimeException("My Message");
}
滿天的星座2017-06-30 09:58:07
This is easy to understand.
Let’s use a simple analogy. Now when you log in, there are user does not exist/password is incorrect...
These error types, if you use RuntimeException
directly, the code should be written like this.
throw new RuntimeException("user not found"); // 用户不存在
throw new RuntimeException("password not match"); // 密码错误
Catch exceptions
try {
// ...逻辑
} catch(RuntimeException e) {
if("user not found".equals(e.getMessage())) {
// ...逻辑
} else if("password not match".equals(e.getMessage())) {
// ...逻辑
}
}
On the contrary, the custom exception is implemented as follows:
throw new UserNotFoundException("user not found"); // 用户不存在
throw new PasswordNotMatchException("password not match"); // 密码错误
Catch exceptions
try {
// ...逻辑
} catch(UserNotFoundException e) {
// ...逻辑
} catch(PasswordNotMatchException e) {
// ...逻辑
}
There are many disadvantages in judging and handling exception logic through message
. For example, message
is dynamic, which will not be handled accurately.
Of course, we can also define a general exception type, and judging by business code will be more accurate. At the same time, It will also reduce the definition of exception types and reduce code redundancy. Below is a piece of kotlin
code, which is the way I currently use it.
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
}
女神的闺蜜爱上我2017-06-30 09:58:07
The explanation is quite clear, making it easy to capture and process
扔个三星炸死你2017-06-30 09:58:07
Exception names must be meaningful, RuntimeException names are meaningless
怪我咯2017-06-30 09:58:07
If you throw Exception directly, Nginx will overwrite your defined message and you will not be able to see the specific information.
The recommended approach is to define an exception yourself and inherit RuntimeException. This will help you know what your exception is and make it easier to find problems.