本文目录导读:

- 基础
try-catch结构 - 多个
catch块 try-catch-finally结构try-with-resources(JDK 7+)- 嵌套
try-catch - 自定义异常类
- 常见异常处理模式
- 最佳实践示例
- 关键要点
在Java中捕获异常主要通过 try-catch-finally 或 try-with-resources 结构来实现,以下是详细的案例和说明:
基础 try-catch 结构
public class ExceptionDemo1 {
public static void main(String[] args) {
try {
// 可能抛出异常的代码
int result = 10 / 0; // 算术异常
System.out.println("结果: " + result);
} catch (ArithmeticException e) {
System.out.println("捕获到算术异常: " + e.getMessage());
e.printStackTrace(); // 打印异常堆栈
}
System.out.println("程序继续执行...");
}
}
多个 catch 块
public class ExceptionDemo2 {
public static void main(String[] args) {
try {
String str = null;
System.out.println(str.length()); // NullPointerException
int[] arr = new int[5];
arr[10] = 100; // ArrayIndexOutOfBoundsException
} catch (NullPointerException e) {
System.out.println("空指针异常: " + e);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界异常: " + e);
} catch (Exception e) {
// 捕获所有其他异常(放在最后)
System.out.println("其他异常: " + e);
}
}
}
try-catch-finally 结构
public class ExceptionDemo3 {
public static void main(String[] args) {
java.io.FileReader reader = null;
try {
reader = new java.io.FileReader("test.txt");
// 读取文件操作
} catch (java.io.FileNotFoundException e) {
System.out.println("文件未找到: " + e);
} finally {
// 无论是否发生异常,都会执行
System.out.println("finally 块总是执行");
try {
if (reader != null) {
reader.close(); // 关闭资源
}
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
}
}
try-with-resources(JDK 7+)
import java.io.*;
public class ExceptionDemo4 {
public static void main(String[] args) {
// 自动关闭资源(资源必须实现 AutoCloseable 接口)
try (FileReader reader = new FileReader("test.txt");
BufferedReader br = new BufferedReader(reader)) {
String line = br.readLine();
System.out.println("读取内容: " + line);
} catch (FileNotFoundException e) {
System.out.println("文件未找到: " + e);
} catch (IOException e) {
System.out.println("IO异常: " + e);
}
// 无需 finally 手动关闭资源
}
}
嵌套 try-catch
public class ExceptionDemo5 {
public static void main(String[] args) {
try {
try {
// 内部 try 块
int[] arr = new int[5];
arr[10] = 100;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("内部异常捕获: " + e);
// 可以重新抛出异常到外部
throw new RuntimeException("重新抛出的异常", e);
}
} catch (RuntimeException e) {
System.out.println("外部异常捕获: " + e);
System.out.println("原始原因: " + e.getCause());
}
}
}
自定义异常类
// 自定义异常
class InsufficientBalanceException extends Exception {
public InsufficientBalanceException(String message) {
super(message);
}
}
class BankAccount {
private double balance = 100.0;
public void withdraw(double amount) throws InsufficientBalanceException {
if (amount > balance) {
throw new InsufficientBalanceException("余额不足!当前余额: " + balance);
}
balance -= amount;
System.out.println("取款成功,剩余余额: " + balance);
}
}
public class ExceptionDemo6 {
public static void main(String[] args) {
BankAccount account = new BankAccount();
try {
account.withdraw(200.0);
} catch (InsufficientBalanceException e) {
System.out.println("捕获自定义异常: " + e.getMessage());
}
}
}
常见异常处理模式
public class ExceptionDemo7 {
// 1. 记录日志
private static final java.util.logging.Logger logger =
java.util.logging.Logger.getLogger(ExceptionDemo7.class.getName());
public static void main(String[] args) {
// 2. 抛出异常(不处理,交由上层调用者处理)
try {
validateAge(-5);
} catch (IllegalArgumentException e) {
System.out.println("捕获验证异常: " + e.getMessage());
}
// 3. 转换异常类型
try {
convertException();
} catch (MyBusinessException e) {
System.out.println("业务异常: " + e.getMessage());
if (e.getCause() != null) {
System.out.println("原始原因: " + e.getCause());
}
}
}
public static void validateAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数: " + age);
}
}
public static void convertException() throws MyBusinessException {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
// 将异常转换为业务异常
throw new MyBusinessException("运算错误", e);
}
}
}
// 自定义业务异常
class MyBusinessException extends Exception {
public MyBusinessException(String message) {
super(message);
}
public MyBusinessException(String message, Throwable cause) {
super(message, cause);
}
}
最佳实践示例
public class ExceptionBestPractice {
public static void main(String[] args) {
processFile("data.txt");
}
public static void processFile(String filename) {
// 使用 try-with-resources 自动管理资源
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = reader.readLine()) != null) {
processLine(line);
}
} catch (FileNotFoundException e) {
// 明确告诉用户文件不存在
System.err.println("错误: 文件 '" + filename + "' 未找到");
System.err.println("请检查文件路径是否正确");
} catch (IOException e) {
// 记录日志并给出友好提示
System.err.println("读取文件时发生错误: " + e.getMessage());
// 在正式应用中应记录日志
e.printStackTrace();
} catch (Exception e) {
// 捕获所有未预期的异常
System.err.println("处理文件时发生未知错误");
e.printStackTrace();
}
}
private static void processLine(String line) {
if (line == null || line.isEmpty()) {
throw new IllegalArgumentException("行内容不能为空");
}
System.out.println("处理: " + line);
}
}
关键要点
- 捕获特定异常优于通用异常 - 先捕获具体异常,最后才是
Exception - 使用
finally块释放资源 - 或使用try-with-resources - 避免空的
catch块 - 至少要记录异常 - 异常类型选择:
- 可恢复异常:使用受检异常
- 编程错误:使用运行时异常
- 异常信息要具体 - 提供有意义的异常消息
- 保持异常链完整 - 使用
initCause()或构造函数传递原因异常
这些示例涵盖了Java异常处理的主要方式,根据具体场景选择合适的方式来捕获和处理异常。