MST
星途 面试题库

面试题:Java异常处理机制之自定义异常与异常链

请阐述在Java中如何自定义一个受检异常(Checked Exception)。假设在一个业务逻辑中,需要从数据库读取数据,可能会遇到多种错误,如连接数据库失败、SQL语句执行错误等,你如何通过自定义异常和异常链来准确传递和处理这些错误信息?
24.2万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 自定义受检异常
    • 在Java中,自定义受检异常需要继承Exception类(因为Exception类及其子类,除了RuntimeException及其子类外,都是受检异常)。
    • 例如,假设我们定义一个数据库读取相关的受检异常:
public class DatabaseReadException extends Exception {
    public DatabaseReadException(String message) {
        super(message);
    }

    public DatabaseReadException(String message, Throwable cause) {
        super(message, cause);
    }
}
  1. 使用异常链处理数据库读取错误
    • 连接数据库失败
      • 通常在Java中使用JDBC连接数据库。如果连接失败,JDBC会抛出SQLException。我们可以在自己的业务逻辑中捕获SQLException,并使用异常链包装成我们自定义的DatabaseReadException
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DatabaseReader {
    public static void main(String[] args) {
        try {
            Connection connection = getDatabaseConnection();
            // 后续数据库操作代码
        } catch (DatabaseReadException e) {
            e.printStackTrace();
        }
    }

    private static Connection getDatabaseConnection() throws DatabaseReadException {
        try {
            // 这里是实际的连接数据库代码,假设数据库URL等信息正确设置
            return DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
        } catch (SQLException e) {
            throw new DatabaseReadException("连接数据库失败", e);
        }
    }
}
  • SQL语句执行错误
    • 当执行SQL语句时,如果出现错误,StatementPreparedStatement的执行方法会抛出SQLException。同样地,我们可以捕获它并包装成DatabaseReadException
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DatabaseReader {
    public static void main(String[] args) {
        try {
            Connection connection = getDatabaseConnection();
            ResultSet resultSet = executeQuery(connection, "SELECT * FROM users");
            // 处理结果集代码
        } catch (DatabaseReadException e) {
            e.printStackTrace();
        }
    }

    private static Connection getDatabaseConnection() throws DatabaseReadException {
        try {
            return DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
        } catch (SQLException e) {
            throw new DatabaseReadException("连接数据库失败", e);
        }
    }

    private static ResultSet executeQuery(Connection connection, String sql) throws DatabaseReadException {
        try {
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            return preparedStatement.executeQuery();
        } catch (SQLException e) {
            throw new DatabaseReadException("SQL语句执行错误", e);
        }
    }
}
  1. 异常处理
    • 在调用可能抛出DatabaseReadException的方法时,必须进行异常处理。可以使用try - catch块捕获异常,并根据需要进行处理,例如记录日志、向用户显示友好的错误信息等。
try {
    // 调用可能抛出DatabaseReadException的方法
    someDatabaseOperation();
} catch (DatabaseReadException e) {
    System.err.println("数据库读取出现问题: " + e.getMessage());
    e.printStackTrace();// 打印异常栈信息,方便调试
    // 如果异常链存在,可以获取原始异常
    Throwable cause = e.getCause();
    if (cause instanceof SQLException) {
        SQLException sqlException = (SQLException) cause;
        // 可以进一步处理SQLException的具体错误信息,如错误码等
        System.err.println("SQL错误码: " + sqlException.getErrorCode());
    }
}

通过以上步骤,我们在Java中自定义了受检异常,并利用异常链准确传递和处理了数据库读取过程中的错误信息。