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异常处理机制的重要组成部分,它强制调用者处理可能的异常,提高了代码的健壮性和可维护性。