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