Java自定义异常 #
一、自定义异常概述 #
当Java内置异常不能满足需求时,可以创建自定义异常类。
二、自定义异常步骤 #
2.1 创建异常类 #
java
// 自定义检查异常
public class BusinessException extends Exception {
public BusinessException() {
super();
}
public BusinessException(String message) {
super(message);
}
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
}
2.2 自定义运行时异常 #
java
// 自定义运行时异常
public class ValidationException extends RuntimeException {
public ValidationException() {
super();
}
public ValidationException(String message) {
super(message);
}
public ValidationException(String message, Throwable cause) {
super(message, cause);
}
}
三、自定义异常示例 #
3.1 业务异常 #
java
public class InsufficientBalanceException extends Exception {
private double balance;
private double amount;
public InsufficientBalanceException(double balance, double amount) {
super(String.format("余额不足: 当前余额 %.2f, 需要金额 %.2f", balance, amount));
this.balance = balance;
this.amount = amount;
}
public double getBalance() {
return balance;
}
public double getAmount() {
return amount;
}
}
// 使用
public class BankAccount {
private double balance;
public void withdraw(double amount) throws InsufficientBalanceException {
if (amount > balance) {
throw new InsufficientBalanceException(balance, amount);
}
balance -= amount;
}
}
3.2 参数校验异常 #
java
public class InvalidParameterException extends RuntimeException {
private String parameterName;
private Object parameterValue;
public InvalidParameterException(String parameterName, Object parameterValue, String message) {
super(String.format("参数 '%s' 无效: %s. 值: %s",
parameterName, message, parameterValue));
this.parameterName = parameterName;
this.parameterValue = parameterValue;
}
public String getParameterName() {
return parameterName;
}
public Object getParameterValue() {
return parameterValue;
}
}
// 使用
public void setAge(int age) {
if (age < 0 || age > 150) {
throw new InvalidParameterException("age", age, "年龄必须在0-150之间");
}
this.age = age;
}
3.3 用户不存在异常 #
java
public class UserNotFoundException extends RuntimeException {
private Long userId;
public UserNotFoundException(Long userId) {
super("用户不存在: ID = " + userId);
this.userId = userId;
}
public Long getUserId() {
return userId;
}
}
// 使用
public User getUserById(Long id) {
User user = userRepository.findById(id);
if (user == null) {
throw new UserNotFoundException(id);
}
return user;
}
四、异常层次结构 #
4.1 设计异常层次 #
java
// 基础业务异常
public abstract class BaseBusinessException extends RuntimeException {
private String errorCode;
public BaseBusinessException(String errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
}
// 用户相关异常
public class UserException extends BaseBusinessException {
public UserException(String errorCode, String message) {
super(errorCode, message);
}
}
public class UserNotFoundException extends UserException {
public UserNotFoundException(Long userId) {
super("USER_001", "用户不存在: " + userId);
}
}
public class UserDisabledException extends UserException {
public UserDisabledException(Long userId) {
super("USER_002", "用户已禁用: " + userId);
}
}
// 订单相关异常
public class OrderException extends BaseBusinessException {
public OrderException(String errorCode, String message) {
super(errorCode, message);
}
}
public class OrderNotFoundException extends OrderException {
public OrderNotFoundException(Long orderId) {
super("ORDER_001", "订单不存在: " + orderId);
}
}
4.2 统一异常处理 #
java
public class ExceptionHandler {
public void handle(Exception e) {
if (e instanceof BaseBusinessException) {
BaseBusinessException be = (BaseBusinessException) e;
System.out.println("错误码: " + be.getErrorCode());
System.out.println("错误信息: " + be.getMessage());
} else {
System.out.println("系统错误: " + e.getMessage());
}
}
}
五、异常信息国际化 #
5.1 支持多语言 #
java
public class I18nException extends RuntimeException {
private String messageKey;
private Object[] args;
public I18nException(String messageKey, Object... args) {
super(messageKey);
this.messageKey = messageKey;
this.args = args;
}
public String getLocalizedMessage(Locale locale) {
ResourceBundle bundle = ResourceBundle.getBundle("messages", locale);
return String.format(bundle.getString(messageKey), args);
}
}
// 使用
throw new I18nException("error.user.not.found", userId);
六、最佳实践 #
6.1 选择合适的父类 #
java
// 检查异常:强制调用者处理
public class DataFormatException extends Exception { }
// 运行时异常:调用者可选处理
public class ValidationException extends RuntimeException { }
6.2 提供多个构造方法 #
java
public class CustomException extends RuntimeException {
public CustomException() {
super();
}
public CustomException(String message) {
super(message);
}
public CustomException(Throwable cause) {
super(cause);
}
public CustomException(String message, Throwable cause) {
super(message, cause);
}
}
6.3 添加有用的属性 #
java
public class BusinessException extends RuntimeException {
private String errorCode;
private Map<String, Object> details;
public BusinessException(String errorCode, String message) {
super(message);
this.errorCode = errorCode;
this.details = new HashMap<>();
}
public BusinessException addDetail(String key, Object value) {
details.put(key, value);
return this;
}
public String getErrorCode() {
return errorCode;
}
public Map<String, Object> getDetails() {
return details;
}
}
// 使用
throw new BusinessException("ERR_001", "操作失败")
.addDetail("userId", 123)
.addDetail("operation", "delete");
七、总结 #
| 要点 | 说明 |
|---|---|
| 继承Exception | 检查异常 |
| 继承RuntimeException | 运行时异常 |
| 提供构造方法 | 无参、消息、原因 |
| 添加属性 | 错误码、详细信息 |
自定义异常要点:
- 根据需要选择检查异常或运行时异常
- 提供有意义的错误信息
- 添加有用的属性和方法
- 设计合理的异常层次结构
最后更新:2026-03-26