简介

在 Java 中,异常处理是一种应对程序运行过程中可能出现的错误或异常事件的机制。Java 提供了一套强大的异常处理框架,确保程序能够优雅地处理错误,而不会导致程序崩溃 😎

异常类

异常类层次结构图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java.lang.Throwable
├── java.lang.Exception
│ ├── java.lang.RuntimeException
│ │ ├── NullPointerException
│ │ ├── ArithmeticException
│ │ ├── IndexOutOfBoundsException
│ │ └── ...
│ ├── IOException
│ ├── SQLException
│ └── ...
└── java.lang.Error
├── OutOfMemoryError
├── StackOverflowError
├── VirtualMachineError
└── ...

Throwable 类

所有的异常类都继承自Throwable类,Throwable 有两个重要子类:

  • Exception:应用程序可能需要处理的可检查异常
  • Error:严重错误,如内存溢出等,程序不应尝试捕捉这些问题

常用方法:

方法名称 说明
public String getMessage() 放回 throwable 的详细消息字符串
public String toString() 返回异常对象的类型和描述信息
public void printStackTrace() 在标准错误流中打印异常的堆栈跟踪信息
public StackTraceElement[] getStackTrace() 返回表示异常堆栈跟踪的数组,每个元素都是一个 StackTraceElement 对象,包含文件名、类名、方法名和行号
public Throwable getCause() 返回导致当前异常的原因(另一个 Throwable 对象),即链式异常中的原始异常。

Exception 类

Exception是程序中常见的异常类型,它代表程序中可预见的错误情况,开发者可以通过捕获异常来处理。

Exception 的两种类型:

  1. 受检查异常(Checked Exception):
  • 必须在编译时处理(通过 try-catch 或 throws 关键字声明)
  • 常见的受检查异常包括:
    • IOException
    • SQLException
    • ClassNotFoundException
  1. 非受检查异常(Unchecked Exception):
  • 继承自 RuntimeException,编译器不会强制要求处理,通常由编程错误引发。
  • 常见的非受检查异常包括:
    • NullPointerException
    • ArrayIndexOutOfBoundsException
    • ArithmeticException

Error 类

Error 类表示严重的系统错误,这些错误通常是不可恢复的,程序不应该捕获或处理这些错误。例如,内存不足(OutOfMemoryError)或虚拟机错误(VirtualMachineError)。开发者通常不用显式地处理这些异常,因为它们反映了运行时环境的不可恢复问题。

异常处理的语法

使用 try-catch-finally 结构来处理异常,语法如下:

1
2
3
4
5
6
7
8
9
try {
// 可能会抛出异常的代码
} catch (异常类型1 e) {
// 处理异常
} catch (异常类型2 e) {
// 处理异常
} finally {
// 可选的finally块,始终执行的代码
}

异常的抛出

  • throw:可以在方法中显式抛出异常并结束这个方法
  • throws:用于声明方法可能抛出的异常,告诉调用者可能会遇到的异常,如果在方法体中抛出了受检查异常则必须在方法名处声明,非受检查异常则不必须
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void main(String[] args) {
int[] arr = {};
try {
getMax(arr);
}catch (Exception e){
e.printStackTrace();
}
}

public static int getMax(int[] arr){
if (arr == null) {
throw new NullPointerException("空指针异常");
}
if (arr.length == 0) {
throw new ArrayIndexOutOfBoundsException("数组长度为零");
}
int max = arr[0];
for (int i : arr) {
if (i > max) {
max = i;
}
}
return max;
}

异常的链式抛出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ChainExceptionExample {
public static void main(String[] args) {
try {
method1();
} catch (Exception e) {
e.printStackTrace(); // 打印堆栈跟踪
}
}

public static void method1() throws Exception {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
throw new Exception("除零错误", e); // 链式异常
}
}
}

输出:

1
2
3
4
5
6
java.lang.Exception: 除零错误
at ChainExceptionExample.method1(ChainExceptionExample.java:11)
at ChainExceptionExample.main(ChainExceptionExample.java:5)
Caused by: java.lang.ArithmeticException: / by zero
at ChainExceptionExample.method1(ChainExceptionExample.java:9)
... 1 more