Java自定义异常案例怎么开发

wen java案例 22

本文目录导读:

Java自定义异常案例怎么开发

  1. 基础自定义异常
  2. 实际业务案例:银行账户系统
  3. 测试代码
  4. 最佳实践建议
  5. 企业级应用中的扩展

我来详细介绍Java自定义异常的开发案例,从基础到进阶。

基础自定义异常

自定义受检异常(Checked Exception)

// 自定义受检异常类
public class InsufficientBalanceException extends Exception {
    // 无参构造器
    public InsufficientBalanceException() {
        super();
    }
    // 带有异常信息的构造器
    public InsufficientBalanceException(String message) {
        super(message);
    }
    // 带有异常信息和原因的构造器
    public InsufficientBalanceException(String message, Throwable cause) {
        super(message, cause);
    }
    // 带有原因的构造器
    public InsufficientBalanceException(Throwable cause) {
        super(cause);
    }
}

自定义非受检异常(Unchecked Exception)

// 自定义运行时异常
public class InvalidAccountException extends RuntimeException {
    public InvalidAccountException() {
        super();
    }
    public InvalidAccountException(String message) {
        super(message);
    }
    public InvalidAccountException(String message, Throwable cause) {
        super(message, cause);
    }
}

实际业务案例:银行账户系统

完整的异常类定义

// 1. 账户相关异常基类
public class AccountException extends Exception {
    private String errorCode;
    public AccountException(String message, String errorCode) {
        super(message);
        this.errorCode = errorCode;
    }
    public String getErrorCode() {
        return errorCode;
    }
}
// 2. 余额不足异常
public class InsufficientBalanceException extends AccountException {
    private double currentBalance;
    private double requiredAmount;
    public InsufficientBalanceException(double currentBalance, double requiredAmount) {
        super(
            String.format("余额不足!当前余额: %.2f, 需要: %.2f", currentBalance, requiredAmount),
            "INSUFFICIENT_BALANCE"
        );
        this.currentBalance = currentBalance;
        this.requiredAmount = requiredAmount;
    }
    public double getCurrentBalance() {
        return currentBalance;
    }
    public double getRequiredAmount() {
        return requiredAmount;
    }
}
// 3. 账户锁定异常
public class AccountLockedException extends AccountException {
    private String accountNumber;
    private Date lockTime;
    public AccountLockedException(String accountNumber, Date lockTime) {
        super(
            String.format("账户 %s 已被锁定,锁定时间: %s", accountNumber, lockTime),
            "ACCOUNT_LOCKED"
        );
        this.accountNumber = accountNumber;
        this.lockTime = lockTime;
    }
    public String getAccountNumber() {
        return accountNumber;
    }
    public Date getLockTime() {
        return lockTime;
    }
}
// 4. 转账限额异常
public class TransferLimitExceededException extends AccountException {
    private double transferAmount;
    private double dailyLimit;
    public TransferLimitExceededException(double transferAmount, double dailyLimit) {
        super(
            String.format("转账金额 %.2f 超过日限额 %.2f", transferAmount, dailyLimit),
            "TRANSFER_LIMIT_EXCEEDED"
        );
        this.transferAmount = transferAmount;
        this.dailyLimit = dailyLimit;
    }
    // 提供建议操作
    public String getSuggestion() {
        return "建议:请降低转账金额或联系客服提高限额";
    }
}

业务逻辑实现

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class BankAccountService {
    private Map<String, Account> accounts = new HashMap<>();
    private Map<String, Double> dailyTransferAmount = new HashMap<>();
    private static final double DAILY_TRANSFER_LIMIT = 50000.00;
    // 初始化账户
    public void createAccount(String accountNumber, double initialBalance) {
        Account account = new Account(accountNumber, initialBalance);
        accounts.put(accountNumber, account);
    }
    // 取款操作(演示受检异常)
    public void withdraw(String accountNumber, double amount) 
            throws InsufficientBalanceException, AccountLockedException {
        Account account = getAccount(accountNumber);
        // 检查账户是否锁定
        if (account.isLocked()) {
            throw new AccountLockedException(accountNumber, account.getLockTime());
        }
        // 检查余额是否充足
        if (account.getBalance() < amount) {
            throw new InsufficientBalanceException(account.getBalance(), amount);
        }
        // 执行取款
        account.setBalance(account.getBalance() - amount);
        System.out.println("取款成功!当前余额: " + account.getBalance());
    }
    // 转账操作(演示多个异常处理)
    public void transfer(String fromAccount, String toAccount, double amount) 
            throws InsufficientBalanceException, AccountLockedException, 
                   TransferLimitExceededException {
        // 检查转账限额
        Double dailyTransfer = dailyTransferAmount.getOrDefault(fromAccount, 0.0);
        if (dailyTransfer + amount > DAILY_TRANSFER_LIMIT) {
            throw new TransferLimitExceededException(amount, DAILY_TRANSFER_LIMIT - dailyTransfer);
        }
        // 执行取款(可能抛出 InsufficientBalanceException 或 AccountLockedException)
        withdraw(fromAccount, amount);
        // 存入目标账户
        Account target = getAccount(toAccount);
        target.setBalance(target.getBalance() + amount);
        // 更新日累计转账金额
        dailyTransferAmount.put(fromAccount, dailyTransfer + amount);
        System.out.println("转账成功!");
    }
    // 模拟账户操作(演示运行时异常)
    public void processTransfer(String fromAccount, String toAccount, double amount) {
        try {
            transfer(fromAccount, toAccount, amount);
        } catch (InsufficientBalanceException e) {
            System.err.println("转账失败:" + e.getMessage());
            System.err.println("当前余额: " + e.getCurrentBalance());
        } catch (AccountLockedException e) {
            System.err.println("转账失败:" + e.getMessage());
            // 记录异常到日志
            logError(e);
        } catch (TransferLimitExceededException e) {
            System.err.println("转账失败:" + e.getMessage());
            System.err.println("建议:" + e.getSuggestion());
        } catch (Exception e) {
            System.err.println("未知错误:" + e.getMessage());
            logError(e);
        }
    }
    private Account getAccount(String accountNumber) {
        Account account = accounts.get(accountNumber);
        if (account == null) {
            throw new InvalidAccountException("账户 " + accountNumber + " 不存在");
        }
        return account;
    }
    private void logError(Exception e) {
        // 实际项目中这里会使用日志框架
        System.err.println("错误时间: " + new Date());
        System.err.println("错误类型: " + e.getClass().getName());
        e.printStackTrace();
    }
}
// 账户实体类
class Account {
    private String accountNumber;
    private double balance;
    private boolean locked;
    private Date lockTime;
    public Account(String accountNumber, double balance) {
        this.accountNumber = accountNumber;
        this.balance = balance;
        this.locked = false;
    }
    public String getAccountNumber() { return accountNumber; }
    public double getBalance() { return balance; }
    public void setBalance(double balance) { this.balance = balance; }
    public boolean isLocked() { return locked; }
    public void setLocked(boolean locked) { 
        this.locked = locked;
        if (locked) {
            this.lockTime = new Date();
        }
    }
    public Date getLockTime() { return lockTime; }
}

测试代码

public class BankAccountTest {
    public static void main(String[] args) {
        BankAccountService bankService = new BankAccountService();
        // 创建测试账户
        bankService.createAccount("1001", 10000.00);
        bankService.createAccount("1002", 5000.00);
        System.out.println("=== 测试1: 正常取款 ===");
        try {
            bankService.withdraw("1001", 2000.00);
        } catch (Exception e) {
            System.err.println("取款异常:" + e.getMessage());
        }
        System.out.println("\n=== 测试2: 余额不足 ===");
        try {
            bankService.withdraw("1001", 90000.00);
        } catch (InsufficientBalanceException e) {
            System.err.println("取款失败:" + e.getMessage());
        } catch (Exception e) {
            System.err.println("其他异常:" + e.getMessage());
        }
        System.out.println("\n=== 测试3: 运行时异常 ===");
        try {
            bankService.processTransfer("1003", "1002", 1000.00);
        } catch (Exception e) {
            System.err.println("转账失败:" + e.getMessage());
        }
        System.out.println("\n=== 测试4: 复杂业务处理 ===");
        bankService.processTransfer("1001", "1002", 3000.00);
        System.out.println("\n=== 测试5: 转账超限 ===");
        bankService.processTransfer("1001", "1002", 100000.00);
    }
}

最佳实践建议

异常设计原则

public class ExceptionBestPractices {
    // ✅ 正确:提供有意义的异常信息
    public class UserNotFoundException extends RuntimeException {
        public UserNotFoundException(String userId) {
            super(String.format("用户 %s 不存在", userId));
        }
    }
    // ❌ 错误:缺乏有意义的异常信息
    public class UserNotFoundException extends RuntimeException {
        public UserNotFoundException() {
            super(); // 没有有用的信息
        }
    }
    // ✅ 正确:包含错误码
    public class BusinessException extends Exception {
        private String errorCode;
        public BusinessException(String message, String errorCode) {
            super(message);
            this.errorCode = errorCode;
        }
    }
    // 异常处理的最佳实践方法
    public void handleExceptionExample() {
        try {
            // 业务操作
            riskyOperation();
        } catch (SpecificException e) {
            // ✅ 记录异常
            logger.error("业务异常", e);
            // ✅ 用户友好的错误信息
            return errorResponse(e.getErrorCode(), e.getMessage());
        } catch (Exception e) {
            // ✅ 异常转换
            throw new BusinessException("系统繁忙,请稍后重试", "SYSTEM_ERROR", e);
        }
    }
}

企业级应用中的扩展

// 统一的异常响应
public class ErrorResponse {
    private String errorCode;
    private String message;
    private String timestamp;
    private String path;
    // getter/setter...
}
// 全局异常处理器
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(AccountException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleAccountException(AccountException e) {
        return new ErrorResponse(
            e.getErrorCode(),
            e.getMessage(),
            new Date().toString(),
            // 获取当前请求路径
        );
    }
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorResponse handleGenericException(Exception e) {
        return new ErrorResponse(
            "UNKNOWN_ERROR",
            "系统繁忙,请稍后重试",
            new Date().toString(),
            ""
        );
    }
}

这个案例覆盖了自定义异常的各个方面,包括:

  • 不同类型的异常(受检/非受检)
  • 丰富的异常信息
  • 实际业务场景
  • 异常处理的最佳实践
  • 企业级应用扩展

抱歉,评论功能暂时关闭!