自定义异常
Java 自带的异常够用吗?大多数时候够。但当你需要表达业务含义时,自定义异常就派上用场了。
异常继承体系
| 异常类型 | 特点 |
|---|---|
| Exception | 受检异常,需处理 |
| RuntimeException | 非受检异常 |
基本自定义异常
java
public class CustomExceptionDemo {
// 继承 Exception(受检异常)
static class UserNotFoundException extends Exception {
public UserNotFoundException(String message) {
super(message);
}
}
// 继承 RuntimeException(非受检异常)
static class InvalidArgumentException extends RuntimeException {
public InvalidArgumentException(String message) {
super(message);
}
}
// 使用
static User getUser(Long id) throws UserNotFoundException {
if (id == null) {
throw new UserNotFoundException("用户不存在");
}
return new User(id);
}
}带错误码的异常
有时候业务需要错误码,方便前端做判断:
java
public class ErrorCodeException extends RuntimeException {
private final int errorCode;
public ErrorCodeException(int errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public int getErrorCode() {
return errorCode;
}
public static void main(String[] args) {
try {
throw new ErrorCodeException(1001, "参数错误");
} catch (ErrorCodeException e) {
System.out.println("错误码: " + e.getErrorCode());
System.out.println("错误信息: " + e.getMessage());
}
}
}异常链
底层异常发生时,包装成业务异常,同时保留原始异常信息:
java
public class ExceptionChainDemo {
static class BusinessException extends RuntimeException {
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
}
public static void main(String[] args) {
try {
// 底层异常
throw new NullPointerException("原始错误");
} catch (NullPointerException e) {
// 包装成业务异常
throw new BusinessException("业务处理失败", e);
}
}
}这样做的好处是:上层能看到完整的异常链路,排查问题时不会一头雾水。
命名规范
自定义异常命名以 Exception 结尾,让代码阅读者一眼就知道这是个异常类:
java
// 好命名
class UserNotFoundException extends Exception {}
class BusinessException extends RuntimeException {}
// 差命名
class UserNotFound extends Exception {}
class BusinessError extends RuntimeException {}