
## 1. 异常分类

### 1.1 检查型异常 (Checked Exceptions)
- 必须处理，否则编译不通过
- 继承自 `Exception`
- 示例：`IOException`, `SQLException`, `ClassNotFoundException`

### 1.2 非检查型异常 (Unchecked Exceptions)
- 不需要强制处理
- 继承自 `RuntimeException`
- 示例：`NullPointerException`, `ArrayIndexOutOfBoundsException`, `IllegalArgumentException`

### 1.3 错误 (Errors)
- 系统级错误，程序通常无法恢复
- 继承自 `Error`
- 示例：`OutOfMemoryError`, `StackOverflowError`

## 2. 异常处理机制

### 2.1 try-catch-finally 块
```java
try {
    // 可能抛出异常的代码
    FileInputStream file = new FileInputStream("test.txt");
    int data = file.read();
} catch (FileNotFoundException e) {
    // 处理特定异常
    System.out.println("文件未找到: " + e.getMessage());
} catch (IOException e) {
    // 处理IO异常
    System.out.println("IO错误: " + e.getMessage());
} finally {
    // 无论是否发生异常都会执行
    System.out.println("清理资源");
    // file.close(); // 实际应该在这里关闭资源
}
```

### 2.2 try-with-resources (Java 7+)
```java
// 自动关闭资源，实现AutoCloseable接口的资源
try (FileInputStream file = new FileInputStream("test.txt");
     BufferedReader reader = new BufferedReader(new InputStreamReader(file))) {
    
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException e) {
    System.out.println("读取文件失败: " + e.getMessage());
}
// 不需要finally块，资源会自动关闭
```

### 2.3 多重捕获 (Java 7+)
```java
try {
    // 可能抛出多种异常的代码
    processFile();
} catch (FileNotFoundException | SecurityException e) {
    // 同时处理多种异常
    System.out.println("文件访问错误: " + e.getMessage());
} catch (IOException e) {
    System.out.println("IO错误: " + e.getMessage());
}
```

## 3. 抛出异常

### 3.1 声明抛出异常 (throws)
```java
public void readFile(String filename) throws FileNotFoundException, IOException {
    if (filename == null) {
        throw new IllegalArgumentException("文件名不能为null");
    }
    // 读取文件操作
}
```

### 3.2 手动抛出异常 (throw)
```java
public void setAge(int age) {
    if (age < 0 || age > 150) {
        throw new IllegalArgumentException("年龄必须在0-150之间: " + age);
    }
    this.age = age;
}
```

## 4. 自定义异常

```java
// 自定义检查型异常
class InsufficientFundsException extends Exception {
    private double amount;
    
    public InsufficientFundsException(double amount) {
        super("资金不足，缺少: " + amount);
        this.amount = amount;
    }
    
    public double getAmount() {
        return amount;
    }
}

// 自定义非检查型异常
class BusinessException extends RuntimeException {
    public BusinessException(String message) {
        super(message);
    }
    
    public BusinessException(String message, Throwable cause) {
        super(message, cause);
    }
}
```

## 5. 异常链

```java
public void processData() throws DataProcessingException {
    try {
        // 某些操作
        readFromDatabase();
    } catch (SQLException e) {
        // 保留原始异常信息
        throw new DataProcessingException("数据处理失败", e);
    }
}
```

## 6. 异常处理的最佳实践

### 6.1 应该做的 ✅
```java
// 1. 提供有意义的异常信息
throw new IllegalArgumentException("用户名不能为空");

// 2. 保留异常链
catch (IOException e) {
    throw new BusinessException("业务处理失败", e);
}

// 3. 在合适的层次处理异常
public void processUserRequest() {
    try {
        validateRequest();
        processBusiness();
    } catch (ValidationException e) {
        logger.warn("请求验证失败", e);
        sendErrorResponse("请求参数错误");
    } catch (BusinessException e) {
        logger.error("业务处理失败", e);
        sendErrorResponse("系统繁忙，请稍后重试");
    }
}

// 4. 使用具体的异常类型
// 好：
} catch (FileNotFoundException e) {
// 不好：
} catch (Exception e) {
```

### 6.2 不应该做的 ❌
```java
// 1. 不要忽略异常
try {
    file.delete();
} catch (SecurityException e) {
    // 错误：空的catch块
}

// 2. 不要过度使用检查型异常
public void someMethod() throws Exception { // 太宽泛

// 3. 不要在finally块中抛出异常
finally {
    resource.close(); // 如果close()抛出异常，会掩盖原始异常
}

// 4. 不要用异常控制流程
// 错误示例：
try {
    while (true) {
        list.get(index);
        index++;
    }
} catch (IndexOutOfBoundsException e) {
    // 用异常来结束循环
}
```

## 7. 常见的异常处理模式

### 7.1 重试机制
```java
public void retryOperation(int maxRetries) {
    int retries = 0;
    while (retries < maxRetries) {
        try {
            performOperation();
            break; // 成功则退出循环
        } catch (TemporaryException e) {
            retries++;
            if (retries >= maxRetries) {
                throw new PermanentException("操作失败，已达到最大重试次数", e);
            }
            waitForRetry(retries);
        }
    }
}
```

### 7.2 优雅降级
```java
public String getConfigValue(String key) {
    try {
        return readFromDatabase(key);
    } catch (DatabaseException e) {
        logger.warn("数据库读取失败，使用默认配置", e);
        return getDefaultValue(key); // 降级方案
    }
}
```

## 总结

| 场景 | 推荐做法 | 不推荐做法 |
|------|----------|------------|
| 资源管理 | try-with-resources | 手动try-catch-finally |
| 异常信息 | 提供具体描述 | 使用泛泛的消息 |
| 异常处理 | 在合适层级处理 | 过早捕获或完全忽略 |
| 异常类型 | 使用具体异常类型 | 捕获过于宽泛的Exception |
| 自定义异常 | 继承合适的父类 | 滥用RuntimeException |

**核心原则**：异常应该用于处理真正"异常"的情况，不应该用于控制正常的程序流程。合理的异常处理能够提高代码的健壮性和可维护性。