Java案例如何实现异常处理?

wen python案例 3

本文目录导读:

Java案例如何实现异常处理?

  1. 核心实现方式
  2. 完整案例:银行转账系统
  3. 最佳实践与注意事项
  4. 异常处理流程图

在Java中实现异常处理主要涉及捕获异常声明异常两种机制,以下是完整的实现方法和最佳实践案例。

核心实现方式

try-catch-finally 结构(最常用)

public class ExceptionDemo {
    public static void main(String[] args) {
        try {
            // 可能发生异常的代码
            int result = 10 / 0;  // 会抛出 ArithmeticException
            System.out.println("结果: " + result);
        } catch (ArithmeticException e) {
            // 处理特定异常
            System.out.println("算术异常: " + e.getMessage());
        } catch (Exception e) {
            // 处理其他异常(通用捕获)
            System.out.println("其他异常: " + e);
        } finally {
            // 无论是否异常都会执行(资源清理)
            System.out.println("finally块 - 一定会执行");
        }
    }
}

throws 声明异常(交给调用者处理)

import java.io.*;
public class ThrowsExample {
    public static void main(String[] args) {
        try {
            readFile("test.txt");
        } catch (IOException e) {
            System.out.println("文件读取失败: " + e.getMessage());
        }
    }
    // 声明该方法可能抛出IOException
    public static void readFile(String path) throws IOException {
        FileReader reader = new FileReader(path);
        BufferedReader br = new BufferedReader(reader);
        System.out.println(br.readLine());
        br.close();
    }
}

throw 手动抛出异常

public class ThrowExample {
    public static void main(String[] args) {
        try {
            validateAge(-5);
        } catch (IllegalArgumentException e) {
            System.out.println("输入验证失败: " + e.getMessage());
        }
    }
    public static void validateAge(int age) {
        if (age < 0) {
            throw new IllegalArgumentException("年龄不能为负数: " + age);
        }
        System.out.println("年龄有效: " + age);
    }
}

完整案例:银行转账系统

// 自定义异常类
class InsufficientBalanceException extends Exception {
    public InsufficientBalanceException(String message) {
        super(message);
    }
}
class NegativeAmountException extends RuntimeException {
    public NegativeAmountException(String message) {
        super(message);
    }
}
// 银行账户类
class BankAccount {
    private String accountNo;
    private double balance;
    public BankAccount(String accountNo, double initialBalance) {
        this.accountNo = accountNo;
        this.balance = initialBalance;
    }
    // 取款方法 - 声明受检异常
    public void withdraw(double amount) throws InsufficientBalanceException {
        if (amount <= 0) {
            throw new NegativeAmountException("取款金额必须为正数");
        }
        if (amount > balance) {
            throw new InsufficientBalanceException("余额不足,当前余额: " + balance);
        }
        balance -= amount;
        System.out.println("取款成功,当前余额: " + balance);
    }
    // 存款方法
    public void deposit(double amount) {
        if (amount <= 0) {
            throw new NegativeAmountException("存款金额必须为正数");
        }
        balance += amount;
        System.out.println("存款成功,当前余额: " + balance);
    }
    public double getBalance() {
        return balance;
    }
}
// 转账服务类
class TransferService {
    public static void transfer(BankAccount from, BankAccount to, double amount) 
            throws InsufficientBalanceException {
        try {
            // 使用try-with-resources(假设数据库连接)
            System.out.println("开始转账...");
            from.withdraw(amount);
            to.deposit(amount);
            System.out.println("转账成功!");
        } catch (InsufficientBalanceException e) {
            // 记录日志
            System.out.println("转账失败: " + e.getMessage());
            throw e;  // 重新抛出异常
        } finally {
            // 释放资源(如数据库连接)
            System.out.println("转账操作完成,资源已释放");
        }
    }
}
// 主程序
public class BankingSystem {
    public static void main(String[] args) {
        BankAccount accountA = new BankAccount("1001", 5000);
        BankAccount accountB = new BankAccount("1002", 2000);
        System.out.println("=== 账户初始状态 ===");
        System.out.println("账户A余额: " + accountA.getBalance());
        System.out.println("账户B余额: " + accountB.getBalance());
        // 场景1:正常转账
        System.out.println("\n=== 场景1:正常转账2000 ===");
        try {
            TransferService.transfer(accountA, accountB, 2000);
        } catch (InsufficientBalanceException e) {
            System.out.println("主程序处理: " + e.getMessage());
        }
        System.out.println("\n转账后账户状态:");
        System.out.println("账户A余额: " + accountA.getBalance());
        System.out.println("账户B余额: " + accountB.getBalance());
        // 场景2:余额不足转账
        System.out.println("\n=== 场景2:余额不足转账8000 ===");
        try {
            TransferService.transfer(accountA, accountB, 8000);
        } catch (InsufficientBalanceException e) {
            System.out.println("主程序处理: " + e.getMessage());
        }
        // 场景3:非法金额(运行时异常)
        System.out.println("\n=== 场景3:非法金额 -500 ===");
        try {
            TransferService.transfer(accountA, accountB, -500);
        } catch (InsufficientBalanceException e) {
            System.out.println("主程序处理: " + e.getMessage());
        } catch (NegativeAmountException e) {
            System.out.println("输入验证失败: " + e.getMessage());
        }
        // 场景4:使用多重catch和finally
        System.out.println("\n=== 场景4:多重异常处理 ===");
        try {
            accountA.deposit(-100);
        } catch (NegativeAmountException e) {
            System.out.println("捕获到运行时异常: " + e.getMessage());
        } finally {
            System.out.println("存款操作尝试完成");
        }
    }
}

最佳实践与注意事项

异常类型选择策略

// ✅ 正确:使用具体异常类型
public void readConfig() throws IOException {
    // 文件读取操作
}
// ❌ 错误:捕获Exception太宽泛
try {
    // 业务代码
} catch (Exception e) {  // 会捕获所有异常,包括运行时异常
    // 处理
}
// ✅ 正确:精确捕获
try {
    // 数据库操作
} catch (SQLException e) {
    // 处理SQL异常
} catch (IOException e) {
    // 处理IO异常
}

资源管理(Java 7+ try-with-resources)

// ✅ 使用try-with-resources自动关闭资源
public void readFile(String path) {
    try (FileReader reader = new FileReader(path);
         BufferedReader br = new BufferedReader(reader)) {
        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    } catch (IOException e) {
        System.err.println("文件读取错误: " + e.getMessage());
    }
    // 不需要手动关闭,资源会自动关闭
}

异常日志记录

import java.util.logging.Logger;
import java.util.logging.Level;
public class LoggingExample {
    private static final Logger LOGGER = Logger.getLogger(LoggingExample.class.getName());
    public void process() {
        try {
            // 业务代码
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "处理失败: " + e.getMessage(), e);
            throw new RuntimeException("业务处理失败", e);  // 将受检异常转为运行时异常
        }
    }
}

异常转化和包装

// 将底层异常转化为业务异常
public class UserService {
    public User findUser(String id) throws UserNotFoundException {
        try {
            // 调用数据库
            User user = userDao.findById(id);
            if (user == null) {
                throw new UserNotFoundException("用户不存在: " + id);
            }
            return user;
        } catch (DataAccessException e) {
            // 包装为业务异常
            throw new UserServiceException("查询用户失败", e);
        }
    }
}

异常处理原则

public class ExceptionPrinciples {
    // ✅ 原则1:不忽略异常
    try {
        // 代码
    } catch (Exception e) {
        // ❌ 空catch块是危险的
        // 至少应该记录日志
        e.printStackTrace();  // 至少打印
    }
    // ✅ 原则2:不捕获太宽泛的异常
    // ❌ catch (Exception e) 不好
    // ✅ catch (SpecificException e) 好
    // ✅ 原则3:保持调用栈完整
    // ❌ throw new RuntimeException();  // 丢失原始异常
    // ✅ throw new RuntimeException(e);  // 保留原始异常
    // ✅ 原则4:异常信息要有意义
    // ❌ throw new Exception("错误");
    // ✅ throw new ValidationException("用户名不能为空");
}

异常处理流程图

程序执行
    │
    ├── 发生异常?
    │   ├── 否 → 正常执行
    │   └── 是 → 寻找匹配的catch块
    │         │
    │         ├── 找到catch → 执行catch块中的处理代码
    │         │         │
    │         │         ├── 有finally → 执行finally
    │         │         └── 无finally → 继续执行后续代码
    │         │
    │         └── 未找到catch → 方法结束,向上抛出异常
    │               │
    │               └── 直到main方法 → JVM终止程序并打印异常栈

这个案例涵盖了Java异常处理的主要实现方式,包括:

  • try-catch-finally的基本使用
  • 自定义异常
  • 受检异常与非受检异常的区别
  • 异常传播和重新抛出
  • try-with-resources自动资源管理
  • 最佳实践和编码规范

通过这个完整的银行转账系统,你可以理解如何在真实项目中合理运用异常处理机制。

抱歉,评论功能暂时关闭!