# Java 异常处理

异常处理是Java程序设计中的重要组成部分,用于处理程序运行时可能出现的错误情况。

# 异常体系

# 异常层次结构

Throwable
├── Error(错误)
│   ├── OutOfMemoryError
│   ├── StackOverflowError
│   └── ...
└── Exception(异常)
    ├── RuntimeException(运行时异常)
    │   ├── NullPointerException
    │   ├── ArrayIndexOutOfBoundsException
    │   ├── ClassCastException
    │   └── ...
    └── 其他异常
        ├── IOException
        ├── SQLException
        └── ...

# 异常处理机制

# try-catch-finally

try {
    // 可能抛出异常的代码
    int result = 10 / 0;
} catch (ArithmeticException e) {
    // 处理特定类型的异常
    System.out.println("除数不能为零:" + e.getMessage());
} catch (Exception e) {
    // 处理其他类型的异常
    System.out.println("发生异常:" + e.getMessage());
} finally {
    // 无论是否发生异常都会执行的代码
    System.out.println("清理资源");
}

# try-with-resources

// 自动关闭资源
try (FileInputStream fis = new FileInputStream("file.txt");
     BufferedReader br = new BufferedReader(new InputStreamReader(fis))) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}

# 抛出异常

# throws关键字

public void readFile(String filename) throws IOException {
    FileReader reader = new FileReader(filename);
    // 读取文件操作
}

# throw关键字

public void validateAge(int age) {
    if (age < 0) {
        throw new IllegalArgumentException("年龄不能为负数");
    }
}

# 自定义异常

// 自定义检查异常
public class CustomCheckedException extends Exception {
    public CustomCheckedException(String message) {
        super(message);
    }
}

// 自定义运行时异常
public class CustomRuntimeException extends RuntimeException {
    public CustomRuntimeException(String message) {
        super(message);
    }
}

# 异常处理最佳实践

  1. 只捕获可以处理的异常
  2. 在合适的层级处理异常
  3. 提供有意义的错误信息
  4. 正确使用finally块清理资源
  5. 优先使用try-with-resources语句
// 示例:银行转账
public class BankAccount {
    private double balance;
    private String accountNumber;

    public void transfer(BankAccount target, double amount) throws InsufficientFundsException {
        try {
            if (amount <= 0) {
                throw new IllegalArgumentException("转账金额必须大于0");
            }
            if (balance < amount) {
                throw new InsufficientFundsException("余额不足");
            }
            balance -= amount;
            target.deposit(amount);
        } catch (IllegalArgumentException e) {
            // 记录日志
            throw e; // 重新抛出异常
        }
    }

    public void deposit(double amount) {
        if (amount <= 0) {
            throw new IllegalArgumentException("存款金额必须大于0");
        }
        balance += amount;
    }
}

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

# 练习

  1. 实现一个文件复制程序,正确处理可能的IO异常
  2. 创建一个简单的计算器,处理各种可能的输入错误
  3. 设计一个用户注册系统,包含自定义的验证异常

# 高级特性

# 异常链

// 异常链示例
public class ExceptionChainDemo {
    public void processData() throws DataProcessException {
        try {
            readData();
        } catch (IOException e) {
            // 创建新异常,保留原始异常信息
            throw new DataProcessException("数据处理失败", e);
        }
    }

    private void readData() throws IOException {
        throw new IOException("读取文件失败");
    }
}

class DataProcessException extends Exception {
    public DataProcessException(String message, Throwable cause) {
        super(message, cause);
    }
}

# 多异常捕获

// Java 7+ 多异常捕获
try {
    Path path = Paths.get("file.txt");
    String content = Files.readString(path);
    JSONParser parser = new JSONParser();
    parser.parse(content);
} catch (IOException | ParseException e) {
    logger.error("文件处理失败", e);
}

# 异常性能优化

// 异常处理性能优化示例
public class ExceptionPerformance {
    private static final Logger logger = LoggerFactory.getLogger(ExceptionPerformance.class);

    // 不推荐:使用异常控制程序流程
    public boolean badPractice(String key, Map<String, String> map) {
        try {
            String value = map.get(key);
            return value != null;
        } catch (Exception e) {
            return false;
        }
    }

    // 推荐:使用正常的控制结构
    public boolean goodPractice(String key, Map<String, String> map) {
        if (map == null || key == null) {
            return false;
        }
        return map.containsKey(key);
    }

    // 异常日志最佳实践
    public void logException(Exception e) {
        // 记录完整的异常栈信息
        logger.error("操作失败: {}", e.getMessage(), e);
        
        // 对于特定异常进行详细记录
        if (e instanceof SQLException) {
            SQLException sqlEx = (SQLException) e;
            logger.error("SQL State: {}, Error Code: {}",
                sqlEx.getSQLState(), sqlEx.getErrorCode());
        }
    }
}

# 自定义异常处理器

// 全局异常处理器示例
@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleException(Exception e) {
        logger.error("未处理的异常", e);
        ErrorResponse error = new ErrorResponse(
            HttpStatus.INTERNAL_SERVER_ERROR.value(),
            "服务器内部错误",
            e.getMessage()
        );
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {
        logger.warn("业务异常", e);
        ErrorResponse error = new ErrorResponse(
            HttpStatus.BAD_REQUEST.value(),
            "业务处理失败",
            e.getMessage()
        );
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }
}

@Data
@AllArgsConstructor
class ErrorResponse {
    private int status;
    private String error;
    private String message;
}

# 异常处理设计模式

// 使用模板方法模式处理异常
public abstract class AbstractOperation<T> {
    public final T execute() {
        try {
            validateInput();
            T result = doExecute();
            afterExecute(result);
            return result;
        } catch (ValidationException e) {
            handleValidationError(e);
            throw e;
        } catch (Exception e) {
            handleError(e);
            throw new OperationException("操作执行失败", e);
        }
    }

    protected abstract T doExecute() throws Exception;
    protected abstract void validateInput() throws ValidationException;
    protected void afterExecute(T result) {}
    protected void handleValidationError(ValidationException e) {}
    protected void handleError(Exception e) {}
}

// 实现示例
public class UserRegistration extends AbstractOperation<User> {
    private final UserDTO userDTO;
    private final UserService userService;

    @Override
    protected void validateInput() throws ValidationException {
        if (userDTO.getUsername() == null || userDTO.getUsername().isEmpty()) {
            throw new ValidationException("用户名不能为空");
        }
    }

    @Override
    protected User doExecute() throws Exception {
        return userService.register(userDTO);
    }

    @Override
    protected void handleValidationError(ValidationException e) {
        logger.warn("用户注册验证失败: {}", e.getMessage());
    }
}

这些高级特性能帮助你:

  1. 更好地追踪异常源头
  2. 优化异常处理性能
  3. 实现统一的异常处理机制
  4. 设计更健壮的异常处理架构