throws 关键字

概述

throws 关键字用于在方法签名中声明该方法可能抛出的检查异常,调用者必须处理这些异常。

语法格式

public returnType methodName(parameters) throws Exception1, Exception2 {
    // 方法体
}

基本用法

import java.io.*;

public class ThrowsExample {

    // 声明可能抛出FileNotFoundException和IOException
    public static void readFile(String filename) throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream(filename); // 可能抛出FileNotFoundException
        byte[] data = new byte[1024];
        fis.read(data); // 可能抛出IOException
        fis.close();
        System.out.println("文件读取成功");
    }

    // 声明抛出通用异常
    public static void processData(String data) throws Exception {
        if (data == null) {
            throw new IllegalArgumentException("数据不能为null");
        }

        if (data.isEmpty()) {
            throw new RuntimeException("数据不能为空");
        }

        // 模拟可能的异常情况
        if (data.equals("ERROR")) {
            throw new Exception("处理数据时发生错误");
        }

        System.out.println("数据处理成功: " + data);
    }

    public static void main(String[] args) {
        // 必须处理声明的检查异常
        try {
            readFile("test.txt");
        } catch (FileNotFoundException e) {
            System.out.println("文件未找到: " + e.getMessage());
        } catch (IOException e) {
            System.out.println("IO错误: " + e.getMessage());
        }

        try {
            processData("hello");
            processData("ERROR");
        } catch (Exception e) {
            System.out.println("处理错误: " + e.getMessage());
        }
    }
}

异常传播

import java.io.*;

public class ExceptionPropagationExample {

    // 最底层方法声明异常
    public static void lowLevelOperation() throws IOException {
        throw new IOException("底层IO错误");
    }

    // 中间层方法可以选择处理或继续抛出
    public static void middleLevelOperation() throws IOException {
        try {
            lowLevelOperation();
        } catch (IOException e) {
            System.out.println("中间层记录错误: " + e.getMessage());
            throw e; // 重新抛出异常
        }
    }

    // 另一个中间层方法包装异常
    public static void anotherMiddleOperation() throws Exception {
        try {
            lowLevelOperation();
        } catch (IOException e) {
            // 包装为更通用的异常
            throw new Exception("中间层操作失败", e);
        }
    }

    // 顶层方法必须处理所有检查异常
    public static void topLevelOperation() {
        try {
            middleLevelOperation();
        } catch (IOException e) {
            System.out.println("顶层处理IO异常: " + e.getMessage());
        }

        try {
            anotherMiddleOperation();
        } catch (Exception e) {
            System.out.println("顶层处理通用异常: " + e.getMessage());
            System.out.println("原始原因: " + e.getCause().getMessage());
        }
    }

    public static void main(String[] args) {
        topLevelOperation();
    }
}

多个异常声明

import java.io.*;
import java.sql.*;
import java.text.*;

public class MultipleExceptionsExample {

    // 声明多个不相关的异常
    public static void complexOperation(String filename, String dateStr, String sqlQuery) 
            throws IOException, ParseException, SQLException {

        // 可能抛出IOException
        FileInputStream fis = new FileInputStream(filename);
        fis.close();

        // 可能抛出ParseException
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.parse(dateStr);

        // 可能抛出SQLException(模拟)
        if (sqlQuery.contains("DROP")) {
            throw new SQLException("危险的SQL操作");
        }

        System.out.println("复杂操作完成");
    }

    // 调用者需要处理所有声明的异常
    public static void callComplexOperation() {
        try {
            complexOperation("data.txt", "2023-12-25", "SELECT * FROM users");
        } catch (IOException e) {
            System.out.println("文件操作失败: " + e.getMessage());
        } catch (ParseException e) {
            System.out.println("日期解析失败: " + e.getMessage());
        } catch (SQLException e) {
            System.out.println("数据库操作失败: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        callComplexOperation();
    }
}

自定义异常与throws

// 业务异常类
class BusinessException extends Exception {
    public BusinessException(String message) {
        super(message);
    }

    public BusinessException(String message, Throwable cause) {
        super(message, cause);
    }
}

class ValidationException extends BusinessException {
    public ValidationException(String message) {
        super(message);
    }
}

class DataAccessException extends BusinessException {
    public DataAccessException(String message, Throwable cause) {
        super(message, cause);
    }
}

public class CustomExceptionThrowsExample {

    // 数据访问层
    public static void saveToDatabase(String data) throws DataAccessException {
        try {
            // 模拟数据库操作
            if (data.equals("FAIL")) {
                throw new RuntimeException("数据库连接失败");
            }
            System.out.println("数据保存成功: " + data);
        } catch (RuntimeException e) {
            throw new DataAccessException("数据保存失败", e);
        }
    }

    // 业务逻辑层
    public static void validateAndSave(String data) throws ValidationException, DataAccessException {
        // 数据验证
        if (data == null || data.trim().isEmpty()) {
            throw new ValidationException("数据不能为空");
        }

        if (data.length() < 3) {
            throw new ValidationException("数据长度不能少于3个字符");
        }

        // 保存数据
        saveToDatabase(data);
    }

    // 服务层
    public static void processUserInput(String input) throws BusinessException {
        try {
            validateAndSave(input);
            System.out.println("用户输入处理成功");
        } catch (ValidationException | DataAccessException e) {
            // 可以选择处理特定异常或重新抛出
            System.out.println("处理过程中发生错误: " + e.getMessage());
            throw e; // 重新抛出业务异常
        }
    }

    // 控制层 - 最终异常处理
    public static void handleUserRequest(String userInput) {
        try {
            processUserInput(userInput);
        } catch (ValidationException e) {
            System.out.println("用户输入验证失败: " + e.getMessage());
        } catch (DataAccessException e) {
            System.out.println("数据访问错误: " + e.getMessage());
            e.printStackTrace();
        } catch (BusinessException e) {
            System.out.println("业务处理失败: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        // 测试各种情况
        handleUserRequest("validData");  // 正常情况
        handleUserRequest("");           // 验证失败
        handleUserRequest("ab");         // 长度不足
        handleUserRequest("FAIL");       // 数据访问失败
    }
}

throws与方法重写

import java.io.IOException;

// 父类
class FileProcessor {
    // 父类方法声明异常
    public void processFile(String filename) throws IOException {
        System.out.println("父类处理文件: " + filename);
        if (filename.equals("error")) {
            throw new IOException("文件处理错误");
        }
    }

    public void anotherMethod() throws Exception {
        System.out.println("父类的另一个方法");
    }
}

// 子类
class AdvancedFileProcessor extends FileProcessor {

    // 1. 子类可以不声明异常(比父类更严格)
    @Override
    public void processFile(String filename) {
        System.out.println("子类处理文件: " + filename);
        // 不抛出异常
    }

    // 2. 子类可以声明相同的异常
    // @Override
    // public void processFile(String filename) throws IOException {
    //     super.processFile(filename);
    // }

    // 3. 子类可以声明更具体的异常
    // @Override
    // public void processFile(String filename) throws FileNotFoundException {
    //     // FileNotFoundException是IOException的子类
    // }

    // 4. 子类不能声明更广泛的异常
    // @Override
    // public void anotherMethod() throws Exception, RuntimeException {
    //     // 错误:不能添加新的检查异常
    // }

    @Override
    public void anotherMethod() throws RuntimeException {
        // 正确:RuntimeException是非检查异常
        System.out.println("子类的另一个方法");
    }
}

public class InheritanceThrowsExample {
    public static void main(String[] args) {
        FileProcessor processor = new AdvancedFileProcessor();

        try {
            processor.processFile("test.txt");
            processor.anotherMethod();
        } catch (IOException e) {
            System.out.println("IO异常: " + e.getMessage());
        } catch (Exception e) {
            System.out.println("其他异常: " + e.getMessage());
        }
    }
}

throws的最佳实践

import java.io.*;
import java.util.*;

public class ThrowsBestPractices {

    // 1. 声明具体的异常而不是通用Exception
    // 好的做法
    public void readConfigFile(String filename) 
            throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream(filename);
        Properties props = new Properties();
        props.load(fis);
        fis.close();
    }

    // 避免的做法
    // public void readConfigFile(String filename) throws Exception {
    //     // 太宽泛,调用者不知道具体可能出现什么异常
    // }

    // 2. 在适当的层次处理异常
    public void businessLogic() throws BusinessLogicException {
        try {
            lowLevelDataAccess();
        } catch (IOException e) {
            // 转换为业务层异常
            throw new BusinessLogicException("业务处理失败", e);
        }
    }

    private void lowLevelDataAccess() throws IOException {
        // 底层数据访问
        throw new IOException("数据访问失败");
    }

    // 3. 使用异常文档化方法行为
    /**
     * 验证用户输入
     * @param input 用户输入
     * @throws IllegalArgumentException 当输入为null或空时
     * @throws ValidationException 当输入格式不正确时
     */
    public void validateInput(String input) 
            throws IllegalArgumentException, ValidationException {
        if (input == null || input.trim().isEmpty()) {
            throw new IllegalArgumentException("输入不能为空");
        }

        if (!input.matches("[a-zA-Z0-9]+")) {
            throw new ValidationException("输入只能包含字母和数字");
        }
    }

    // 4. 合理使用运行时异常
    public void setAge(int age) {
        // 对于编程错误,使用运行时异常,无需declares
        if (age < 0 || age > 150) {
            throw new IllegalArgumentException("年龄必须在0-150之间");
        }
    }

    // 5. 资源管理的异常处理
    public String readFileContent(String filename) throws IOException {
        try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
            StringBuilder content = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                content.append(line).append("\n");
            }
            return content.toString();
        }
        // try-with-resources自动处理资源关闭的异常
    }

    // 自定义异常类
    static class BusinessLogicException extends Exception {
        public BusinessLogicException(String message, Throwable cause) {
            super(message, cause);
        }
    }

    static class ValidationException extends Exception {
        public ValidationException(String message) {
            super(message);
        }
    }

    public static void main(String[] args) {
        ThrowsBestPractices example = new ThrowsBestPractices();

        try {
            example.readConfigFile("config.properties");
        } catch (FileNotFoundException e) {
            System.out.println("配置文件未找到");
        } catch (IOException e) {
            System.out.println("读取配置文件失败");
        }

        try {
            example.businessLogic();
        } catch (BusinessLogicException e) {
            System.out.println("业务逻辑错误: " + e.getMessage());
        }

        try {
            example.validateInput("valid123");
            example.validateInput("invalid@#$");
        } catch (ValidationException e) {
            System.out.println("验证失败: " + e.getMessage());
        }
    }
}

throws关键字是Java异常处理机制的重要组成部分,它强制调用者处理可能的异常,提高了代码的健壮性和可维护性。

powered by Gitbook© 2025 编外计划 | 最后修改: 2025-07-28 16:25:54

results matching ""

    No results matching ""