Java 异常处理详解
·
异常处理是 Java 编程中不可或缺的一部分,它帮助开发者优雅地处理程序运行时的错误情况,避免程序直接崩溃。以下是 Java 异常处理的核心内容:
异常体系结构
Java 的异常体系以 java.lang.Throwable 为根类,分为两大分支:
- Exception:程序可处理的异常,包括受检异常(Checked Exception)和非受检异常(Unchecked Exception)。
- Error:程序无法处理的严重问题,通常与 JVM 或系统资源相关。
Throwable
├── Error
│ ├── StackOverflowError
│ ├── OutOfMemoryError
│ └── ...
└── Exception
├── RuntimeException
│ ├── NullPointerException
│ ├── ArrayIndexOutOfBoundsException
│ └── ...
└── 其他受检异常
├── IOException
├── FileNotFoundException
└── ...
Exception 与 Error 的区别
Exception
- 程序可以处理的异常。
- 通过
try-catch或throws机制处理。 - 示例:文件不存在、空指针、数组越界等。
Error
- 程序无法处理的严重问题。
- 通常由 JVM 或系统资源问题引起。
- 示例:
StackOverflowError、OutOfMemoryError。 - 不建议捕获
Error,应优化代码逻辑避免。
public class ErrorDemo {
public static void recursiveMethod() {
recursiveMethod(); // 无限递归导致 StackOverflowError
}
public static void main(String[] args) {
recursiveMethod();
}
}
运行时异常与非运行时异常
运行时异常(RuntimeException)
- 继承自
RuntimeException。 - 编译器不强制处理。
- 示例:
NullPointerException、ArrayIndexOutOfBoundsException。 - 通常通过改进代码逻辑避免。
public class NullPointerDemo {
public static void main(String[] args) {
String str = null;
System.out.println(str.length()); // NullPointerException
}
}
非运行时异常(Checked Exception)
- 不继承
RuntimeException。 - 编译器强制处理(捕获或声明抛出)。
- 示例:
IOException、SQLException。
import java.io.*;
public class CheckedExceptionDemo {
public static void main(String[] args) {
try {
FileReader fr = new FileReader("nonexistent.txt");
} catch (FileNotFoundException e) {
System.out.println("文件未找到: " + e.getMessage());
}
}
}
异常处理机制
try-catch-finally
- 直接捕获并处理异常。
finally块用于释放资源。
public class TryCatchDemo {
public static void main(String[] args) {
try {
int a = 10 / 0; // ArithmeticException
} catch (ArithmeticException e) {
System.out.println("捕获到算术异常: " + e.getMessage());
} finally {
System.out.println("执行 finally 块");
}
}
}
throws
- 将异常抛给调用者处理。
- 适用于不适合在当前方法中处理异常的情况。
public class ThrowsDemo {
public static void readFile() throws FileNotFoundException {
FileReader fr = new FileReader("nonexistent.txt");
}
public static void main(String[] args) {
try {
readFile();
} catch (FileNotFoundException e) {
System.out.println("处理文件未找到异常");
}
}
}
多级 catch
- 捕获多种异常时,子类异常应放在父类异常之前。
public class MultiCatchDemo {
public static void main(String[] args) {
try {
int[] array = new int[3];
array[5] = 10; // ArrayIndexOutOfBoundsException
String s = null;
s.length(); // NullPointerException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界: " + e);
} catch (NullPointerException e) {
System.out.println("空指针: " + e);
} catch (Exception e) {
System.out.println("其他异常: " + e);
}
}
}
多异常捕获语法
从 Java 7 开始支持在单个 catch 块中捕获多个异常类型,使用竖线 | 分隔异常类型。这种语法适用于处理逻辑相同的异常场景。
try {
// 可能抛出多种异常的代码
} catch (ArrayIndexOutOfBoundsException | NullPointerException e) {
System.out.println("发生数组越界或空指针异常");
}
finally 块特性
finally 块确保资源释放的执行可靠性,其特点包括:
- 无论是否发生异常都会执行
- 即使 try 或 catch 块中有 return 语句也会执行
- 主要应用于资源清理场景
FileInputStream fis = null;
try {
fis = new FileInputStream("file.txt");
// 文件操作代码
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
try-with-resources 机制
Java 7 引入的自动资源管理语法要求:
- 资源必须实现 AutoCloseable 接口
- 资源声明写在 try 后的括号内
- 退出 try 块后自动调用 close() 方法
try (FileReader reader = new FileReader("test.txt");
BufferedReader br = new BufferedReader(reader)) {
String line = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
throws 声明规范
方法抛出异常时的处理原则:
- 受检异常必须显式声明
- 运行时异常可省略 throws 声明
- 调用声明 throws 的方法必须处理异常
public void readConfig() throws FileNotFoundException {
// 不处理异常直接抛出
new FileInputStream("config.ini");
}
自定义异常实现
创建自定义异常需注意:
- 业务异常建议继承 Exception
- 非强制处理异常继承 RuntimeException
- 应提供包含错误信息的构造方法
class PaymentException extends Exception {
public PaymentException(String message) {
super(message);
}
public PaymentException(String message, Throwable cause) {
super(message, cause);
}
}
异常处理最佳实践
- 避免捕获过于宽泛的异常类型
- 不要用异常替代正常流程控制
- 确保资源释放使用 try-with-resources
- 记录异常日志时包含完整堆栈信息
- 保持异常信息对调试有帮助
// 不良实践示例
try {
// 业务代码
} catch (Exception e) {
// 空的catch块
}
// 推荐做法
try {
// 业务代码
} catch (SpecificException e) {
logger.error("操作失败,参数: {}", param, e);
throw new BusinessException("操作失败", e);
}
更多推荐

所有评论(0)