MST

星途 面试题库

面试题:自定义异常在Java异常类层次结构中的设计与应用

假设你正在开发一个大型金融交易系统,需要自定义异常来处理特定业务逻辑中的异常情况。请说明如何基于Java异常类层次结构设计自定义异常类,包括继承哪个基类,如何合理地重写相关方法,以及在整个系统中如何有效地使用和管理这些自定义异常。
34.2万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

1. 基于Java异常类层次结构设计自定义异常类

  • 继承基类
    • 如果是可恢复的异常,继承Exception类。例如,当用户输入的金额格式正确但超出了系统允许的交易限额时,这是一种业务逻辑异常,可恢复,此时自定义异常类可以继承Exception
    • 如果是不可恢复的异常,例如系统内部的严重错误(如数据库连接池耗尽且无法恢复连接),继承RuntimeException类。在金融交易系统中,这种情况相对较少,但如果发生可能导致系统崩溃,此时继承RuntimeException
  • 示例代码
// 可恢复的自定义异常
public class TransactionLimitExceededException extends Exception {
    public TransactionLimitExceededException(String message) {
        super(message);
    }
}

// 不可恢复的自定义异常
public class DatabaseConnectionPoolExhaustedException extends RuntimeException {
    public DatabaseConnectionPoolExhaustedException(String message) {
        super(message);
    }
}

2. 合理地重写相关方法

  • 重写toString()方法:提供关于异常的简洁描述,包括异常类型和关键信息。例如在TransactionLimitExceededException中:
@Override
public String toString() {
    return "TransactionLimitExceededException: " + getMessage();
}
  • 重写printStackTrace()方法:在需要对异常堆栈信息进行特殊处理时重写。比如在金融交易系统中,可能希望将异常堆栈信息记录到特定的日志文件中,并添加额外的上下文信息(如交易ID)。
@Override
public void printStackTrace() {
    System.err.println("Transaction ID: " + transactionId); // 假设存在交易ID
    super.printStackTrace();
}

3. 在整个系统中有效地使用和管理这些自定义异常

  • 抛出异常:在业务逻辑方法中,当特定条件触发异常时抛出。例如在处理交易金额的方法中:
public void processTransaction(double amount) throws TransactionLimitExceededException {
    if (amount > transactionLimit) {
        throw new TransactionLimitExceededException("Transaction amount exceeds the limit.");
    }
    // 正常交易处理逻辑
}
  • 捕获异常:在调用可能抛出异常的方法处进行捕获。在金融交易系统的交易处理模块中:
try {
    processTransaction(transactionAmount);
} catch (TransactionLimitExceededException e) {
    // 记录异常日志
    logger.error("Transaction limit exceeded", e);
    // 向用户显示友好的错误提示
    displayErrorMessage("交易金额超过限制,请调整金额后重试。");
}
  • 异常传播:如果当前方法无法处理异常,可以将其向上传播给调用者。例如一个底层的数据访问方法抛出DatabaseConnectionPoolExhaustedException,上层的业务逻辑方法可能无法处理,直接向上抛给应用的顶层异常处理模块。
public void dataAccessMethod() throws DatabaseConnectionPoolExhaustedException {
    // 数据库操作代码,可能抛出异常
    if (connectionPool.isEmpty()) {
        throw new DatabaseConnectionPoolExhaustedException("数据库连接池耗尽");
    }
}

public void businessLogicMethod() throws DatabaseConnectionPoolExhaustedException {
    dataAccessMethod();
}
  • 集中异常处理:可以使用try - catch - finally块在关键位置(如Servlet过滤器、Spring AOP切面等)对整个系统的异常进行统一处理,记录日志、返回统一格式的错误响应等。例如在Spring Boot应用中,可以通过@ControllerAdvice注解实现全局异常处理:
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(TransactionLimitExceededException.class)
    public ResponseEntity<String> handleTransactionLimitExceededException(TransactionLimitExceededException e) {
        // 记录日志
        logger.error("Transaction limit exceeded", e);
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("交易金额超过限制,请调整金额后重试。");
    }

    @ExceptionHandler(DatabaseConnectionPoolExhaustedException.class)
    public ResponseEntity<String> handleDatabaseConnectionPoolExhaustedException(DatabaseConnectionPoolExhaustedException e) {
        // 记录日志
        logger.error("Database connection pool exhausted", e);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("系统繁忙,请稍后重试。");
    }
}