1. 认识异常
先从一个简单的类比开始。想象你的程序就像一辆在路上行驶的汽车。一切都很顺利,直到突然发生意外:轮胎没气了、汽油耗尽、发动机过热。如果不“处理”这种情况(例如换备胎或去加油),汽车就会停下来,无法继续行驶。程序也是如此:如果不处理异常,程序会异常终止。
异常(exception)是程序运行过程中出现问题时创建的一个对象。异常在告诉你:“停!出了点问题!”
会抛出异常的典型场景:
- 被零除(10 / 0)
- 访问不存在的数组元素(arr[999])
- 打开磁盘上不存在的文件
- 将字符串 "abc" 转换为数字(Integer.parseInt("abc"))
重要:异常不是编译错误(例如代码中的拼写错误),而是在程序运行过程中出现的问题。
为什么异常是好事?
- 代码更干净:主流程不必被对每个细枝末节的检查所干扰。
- 更灵活:可以集中处理错误(例如把所有文件读取错误放在同一处处理)。
- 更可靠:程序不会莫名其妙地“崩溃”,而是明确告知究竟发生了什么。
2. 异常(Exceptions) vs 错误(Errors)
在 Java 中,运行期间可能出现两大类问题:
错误(Errors)
错误是致命且不可恢复的问题,由 Java 虚拟机(JVM)自身的故障引发。它们通常与计算机资源或 JVM 的内部故障相关。
错误示例:
- OutOfMemoryError —— 内存耗尽。
- StackOverflowError —— 栈溢出(例如由于无限递归)。
重要:通常不应在程序中尝试处理这类错误。
异常(Exceptions)
异常是程序能够(也应该)处理的问题。它们可能由程序逻辑错误或外部因素导致(例如用户输入与预期不符)。
异常示例:
- NullPointerException —— 尝试将 null 当作对象使用。
- ArrayIndexOutOfBoundsException —— 数组越界。
- IOException —— 文件 I/O 操作出错。
Java 中的异常分为两类:
- Checked exceptions(受检)—— 编译器要求显式处理(例如 IOException)。
- Unchecked exceptions(非受检)—— 编译器不要求处理(例如 NullPointerException)。
示意图:层次结构
graph TD
Throwable --> Error
Throwable --> Exception
Exception --> RuntimeException
Exception --> Checked["(其他 Exceptions)"]
style Throwable fill:#ffa64d,color:#000
style Exception fill:#ffa64d,color:#000
style Checked fill:#ffa64d,color:#000
style Error fill:#ff4d4d,color:#fff
style RuntimeException fill:#4dff88,color:#000
说明:
- Throwable —— Java 中错误和异常层次结构的根类型。
- Error —— JVM 的致命错误,不进行处理。
- Exception —— 可以也应该处理的“常规”异常。
- RuntimeException —— 非受检异常(通常是程序员犯的错误)。
3. 在代码中如何体现?
示例 1:被零除
public class ExceptionDemo
{
public static void main(String[] args)
{
int a = 10;
int b = 0;
int c = a / b; // 这里会抛出 ArithmeticException!
System.out.println("结果: " + c);
}
}
会发生什么?
程序会以错误结束,你会看到如下信息:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExceptionDemo.main(ExceptionDemo.java:5)
示例 2:访问不存在的数组元素
int[] arr = {1, 2, 3};
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException
示例 3:文件操作
import java.io.FileReader;
import java.io.IOException;
public class FileDemo
{
public static void main(String[] args) throws IOException
{
FileReader reader = new FileReader("nofile.txt"); // FileNotFoundException (checked)
int data = reader.read();
System.out.println(data);
reader.close();
}
}
接下来我们就来看看如何优雅地处理这些异常情况。
GO TO FULL VERSION