本文目录导读:

我来详细介绍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(),
""
);
}
}
这个案例覆盖了自定义异常的各个方面,包括:
- 不同类型的异常(受检/非受检)
- 丰富的异常信息
- 实际业务场景
- 异常处理的最佳实践
- 企业级应用扩展
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播