本文目录导读:

在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自动资源管理
- 最佳实践和编码规范
通过这个完整的银行转账系统,你可以理解如何在真实项目中合理运用异常处理机制。