⚠️ 异常处理基础
什么是异常 · try-catch-finally 手把手 · 常见异常 · throws 与 throw
1. 什么是异常?程序出错了会怎样?
程序运行中出错(除以 0、数组越界、文件不存在),Java 会"抛出"一个异常对象。如果不处理,程序会崩溃终止。
不处理异常的后果
int[] arr = {1, 2};
System.out.println(arr[5]); // 下标越界!
System.out.println("后面的代码"); // ❌ 这行不会执行,程序已崩溃
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
Index 5 out of bounds for length 2
at Main.main(Main.java:3)
// 报错信息三要素:异常类型 + 描述 + 出错位置(哪行)
🚨 类比——红绿灯故障:异常就像路上出了事故:
不处理 = 整条路瘫痪(程序终止);
try-catch = 交警到场处理(程序继续跑)——这就是异常处理的意义。
不处理 = 整条路瘫痪(程序终止);
try-catch = 交警到场处理(程序继续跑)——这就是异常处理的意义。
🎯 三个认知
- 报错信息要会读:类型(什么错)+ 位置(哪一行)——新手先学会看"第几行"
- 异常不是"程序写得烂",是不可避免的运行时状况(用户乱输入、网络断)——所以要处理
- 异常体系后面深入学(java-basics 模块),这里先会用 try-catch
2. try-catch-finally 怎么写?
完整结构
try {
// ① 放"可能出错的代码"
int r = 10 / 0; // 除零异常在这里发生
System.out.println(r);
} catch (ArithmeticException e) {
// ② 出错时执行(像"交警")
System.out.println("计算出错:" + e.getMessage());
} finally {
// ③ 无论成不成功都执行(像"收尾")
System.out.println("收尾工作");
}
System.out.println("程序继续运行"); // ✅ 不会崩溃
计算出错:/ by zero
收尾工作
程序继续运行
三块各自的作用:
- try:试运行的代码(危险区)
- catch:捕获并处理异常——程序不崩溃,继续执行
- finally:收尾(关文件、关连接)——不管 try 成功还是 catch 了都会执行
🎯 新手注意
- catch 里别什么都不写(吞异常)——至少打印:e.printStackTrace() 或 log
- 一个 try 可以跟多个 catch(不同类型的异常分别处理)
- finally 不是必须的,但"关闭资源"必须放 finally(后面有 try-with-resources 更优雅)
3. 新手最常见的异常有哪些?(看到能认出来)
| 异常 | 什么时候发生 |
|---|---|
| NullPointerException(空指针) | 对 null 调用方法/属性——最最常见的错误 |
| ArrayIndexOutOfBoundsException | 数组下标越界 |
| ArithmeticException | 数学错误(除以 0) |
| NumberFormatException | "abc".parseInt 转数字失败 |
| ClassCastException | 强转类型不对 |
| InputMismatchException | Scanner 输入类型不匹配 |
| FileNotFoundException | 文件不存在(受检异常,编译器强制处理) |
空指针的典型场景和防御
Student s = null;
s.getName(); // ❌ NullPointerException
// 防御:先判空再使用
if (s != null) {
System.out.println(s.getName());
}
// 或:String s2 = ...; if (s2 != null && s2.length() > 0)
// && 短路保证:s2 为 null 时不会执行 length()(见运算符页)
4. throw 和 throws 的区别?
- throw:主动"抛出一个异常"(动词,在方法内部用)——比如参数不合法时主动报错
- throws:声明"我这个方法可能抛出异常"(动词声明,写在方法签名后)——把处理责任推给调用方
throw vs throws
// throw:主动抛出(自己创建异常)
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负");
}
this.age = age;
}
// throws:声明会抛出(交给调用方处理)
public void readFile(String path) throws IOException {
// 读文件,出错时 IOException 往上抛
}
// 调用方要么 try-catch,要么继续 throws
✍️ 练习题
- 1. 写代码故意制造 3 种异常(空指针/越界/除零),观察报错信息
- 2. 用 try-catch 捕获除零异常,程序不崩溃并提示"除数不能为 0"
- 3. 写方法 divide(a,b):b 为 0 时用 throw 抛出 IllegalArgumentException
- 4. 验证 finally 一定执行:try 里 return 1,finally 里打印"清理",看输出顺序
- 5. 思考:try 里 return 了,finally 还会执行吗?(答案:会,finally 在 return 之前执行——这是面试经典题)