掌握自定义异常类的创建和使用,理解异常继承体系与最佳实践
在Java编程中,虽然标准库提供了丰富的异常类型,但在实际开发中,我们经常需要创建自定义异常来更准确地表达特定的错误情况。自定义异常能够提供更清晰的错误信息,便于问题定位和处理。
public class InvalidAgeException extends Exception {
private String errorCode;
public InvalidAgeException(String message, String errorCode) {
super(message);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
}
public class InsufficientFundsException extends RuntimeException {
private double currentBalance;
private double requestedAmount;
public InsufficientFundsException(String message,
double currentBalance, double requestedAmount) {
super(message);
this.currentBalance = currentBalance;
this.requestedAmount = requestedAmount;
}
}
良好的异常继承体系能够提供清晰的异常分类,便于异常处理和维护。设计时应该根据业务领域和错误类型进行合理分层。
// 基础业务异常
abstract class BusinessLogicException extends Exception {
private String errorCode;
public BusinessLogicException(String message, String errorCode) {
super(message);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
}
// 订单相关异常
class InvalidOrderException extends BusinessLogicException {
public InvalidOrderException(String message, String errorCode) {
super(message, errorCode);
}
}
// 用户相关异常
class UserRegistrationException extends BusinessLogicException {
private String failureReason;
public UserRegistrationException(String message, String failureReason) {
super(message, "USER_REGISTRATION_FAILED");
this.failureReason = failureReason;
}
}
异常层级 | 说明 | 使用场景 |
---|---|---|
基础异常类 | 定义通用的异常属性和方法 | 作为其他异常的父类,提供统一接口 |
领域异常类 | 按业务领域分类的异常 | 数据库异常、网络异常、业务异常等 |
具体异常类 | 特定错误情况的异常 | 用户不存在、余额不足、文件未找到等 |
异常链是一种重要的异常处理技术,它允许我们在抛出新异常时保留原始异常的信息,这对于问题诊断和调试非常有用。
public class ServiceException extends Exception {
public ServiceException(String message) {
super(message);
}
public ServiceException(String message, Throwable cause) {
super(message, cause);
}
}
public void businessMethod() throws ServiceException {
try {
// 调用底层方法
databaseOperation();
} catch (SQLException e) {
// 包装为业务异常,保留原始异常
throw new ServiceException("用户服务操作失败", e);
}
}
以下是一个完整的自定义异常使用示例,展示了如何在实际项目中设计和使用自定义异常。
/**
* 自定义异常示例程序
* 演示如何创建和使用自定义异常类
*/
public class CustomExceptionExample {
public static void main(String[] args) {
CustomExceptionExample example = new CustomExceptionExample();
try {
// 测试年龄验证
example.validateAge(15);
} catch (InvalidAgeException e) {
System.out.println("捕获到自定义异常: " + e.getMessage());
System.out.println("错误代码: " + e.getErrorCode());
}
try {
// 测试银行账户操作
BankAccount account = new BankAccount("123456", 1000.0);
account.withdraw(1500.0);
} catch (InsufficientFundsException e) {
System.out.println("银行操作异常: " + e.getMessage());
System.out.println("当前余额: " + e.getCurrentBalance());
System.out.println("尝试提取: " + e.getRequestedAmount());
}
}
/**
* 验证年龄
*
* @param age 年龄
* @throws InvalidAgeException 当年龄无效时抛出
*/
public void validateAge(int age) throws InvalidAgeException {
if (age < 0) {
throw new InvalidAgeException("年龄不能为负数", "AGE_NEGATIVE");
}
if (age > 150) {
throw new InvalidAgeException("年龄不能超过150岁", "AGE_TOO_HIGH");
}
if (age < 18) {
throw new InvalidAgeException("年龄必须满18岁", "AGE_TOO_LOW");
}
System.out.println("年龄验证通过: " + age + "岁");
}
}
// 明确的异常命名
InvalidEmailFormatException
DatabaseConnectionTimeoutException
InsufficientPermissionException
// 提供有用的错误信息
throw new InvalidAgeException(
String.format("年龄%d超出有效范围[0-150]", age),
"AGE_OUT_OF_RANGE"
);
// 保留异常链
try {
lowLevelOperation();
} catch (IOException e) {
throw new ServiceException("服务操作失败", e);
}
// 模糊的异常命名
MyException
BadException
ErrorException
// 丢失原始异常信息
try {
operation();
} catch (Exception e) {
throw new CustomException("操作失败"); // 丢失了原始异常
}
// 过度使用检查型异常
public void setAge(int age) throws InvalidAgeException // 过度