☕ 第五章 异常

5.1 什么是异常

📄 一句话概括

异常 = 程序运行中冒出来的"意外状况",它会打断正常流程。编译能过的代码不代表能跑完——运行时一遇意外,JVM 就现场造出一个异常对象(一份写明类型、消息、位置的事故报告)。4.4 集齐的三大新手异常,本章开始收容。

1. 先分清"三种不对劲"

学异常前先划清界限——"程序出问题"其实有三种,待遇完全不同:

类型 什么时候暴露 典型例子 谁来管
编译错误 编译期,javac 直接拦下 少分号、类名拼错、类型不匹配 编译器,不改不让跑
异常(本章主角) 运行期,编译能过 除零、空指针、数组越界 运行时才炸,Java 提供处理机制
逻辑错误 运行完才发现结果不对 该用 >= 写成了 > 没人管,最阴险,靠测试和调试

1.4 学过"编译型语言编译期就能抓语法错"——但编译器只能查规矩错,查不了路况。10 / 0 语法完全合法,编译器没意见;真跑起来才知道,除数是 0,数学上就不成立。异常管的正是这类"语法没错、路况出了意外"的情况。

2. 生活类比:爆胎不是"车造错了"

开车上班是"正常流程",路上爆胎是"意外状况":

Java 对异常的态度一样:意外可以发生,但不能不了了之——每次意外都必须有人写一份"事故报告"并交给该管的人。这份报告,就是异常对象。

3. 异常在 Java 里的真身:也是对象

看一次真事故。运行下面代码:

public class Demo01 {
    public static void main(String[] args) {
        System.out.println("程序开始");
        int r = 10 / 0;                    // 第 5 行:炸点
        System.out.println("程序结束");    // 永远执行不到
    }
}

控制台输出(红字):

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Demo01.main(Demo01.java:5)

保姆式解读这份报错——三段拆开看:

报错片段 是什么
java.lang.ArithmeticException 异常类型:算术异常类(JDK 自带的类)
/ by zero 异常消息:具体事故原因——除以了零
at Demo01.main(Demo01.java:5) 发生位置:Demo01 类的 main 方法,第 5 行(这叫堆栈跟踪)

关键是想通一件事:这行红字不是凭空打印的,它是 JVM 现场造出的一个对象——当程序跑到 10 / 0 这一刻:

  1. JVM 发现意外(除零);
  2. 现场创建一个 ArithmeticException 类的对象,把类型、消息、发生位置装进去;
  3. 把这个对象抛出(throw)——像把事故报告往上递;
  4. 没人接住 → 报告打印到控制台 → 程序立即中断,第 6 行的"程序结束"永远不执行。

所以你看到的一切异常报错,本质都是某个异常类的对象。异常也是类、也能 new——4.1 学的"万物继承 Object"、4.3 的继承体系,在这里正式上岗:所有异常类都是一家人(下面看家谱)。

4. 异常体系家谱(会认层次,5.2/5.3 反复用)

Throwable(一切"可抛物"的老祖宗)
 ├── Error              —— 严重错误:JVM 级的,程序管不了(如内存耗尽)
 └── Exception          —— 异常:程序可以处理(本章主角)
      ├── RuntimeException —— 运行时异常:编译器不强制处理
      │     ├── ArithmeticException      除零
      │     ├── NullPointerException     空指针(3.2 老朋友)
      │     ├── ArrayIndexOutOfBoundsException  越界(2.7 老朋友)
      │     └── ClassCastException       类型转换失败(4.4 老朋友)
      └── 其他 Exception  —— 编译期异常(受检异常):编译器逼你处理(5.3 见)

家谱上的两个岔路口,判断标准就一条:

📝 RuntimeException 和"编译期异常"的分水岭(先混脸熟)

你炸过的三大新手异常全是 RuntimeException 家的孩子——特点是编译器不拦,运行才炸,所以叫运行时异常。而另一支(如文件找不到、网络断了)编译器强制你写处理代码,不写连编译都过不了——所以叫"受检异常",5.2 学 try-catch 时会亲眼见到编译器怎么逼你。

5. 异常不处理会怎样:程序当场中断

再用一个实验看清"中断"的杀伤力:

public class Demo02 {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3};
        System.out.println(arr[5]);        // 越界:最大索引才 2
        System.out.println("重要收尾工作"); // 执行不到!
    }
}

越界异常一抛出,main 立刻中断——后面的代码一行都不会跑。如果"收尾工作"里是保存文件、释放资源,那就真出事故了。这就是异常必须被"管理"的原因:不是让报错好看点,而是保证意外发生时程序还能体面地收场。

6. 动手:亲手制造并阅读一次事故

新建项目 IDEA05,新建 Demo01(照第 3 节抄),运行并完成三个实验:

三个 30 秒实验

  1. 读报告:认真看报错红字,用手指分别指出异常类型、消息、位置三段——读报错是本章的核心技能,比背概念重要十倍。
  2. 改炸点:把 10 / 0 改成 int[] arr = new int[3]; arr[5] = 1;——报错类型变成 ArrayIndexOutOfBoundsException,报告格式一模一样。
  3. 看中断:在炸点后面再加一行打印,运行确认它永远不执行——体会"异常 = 流程被打断"。

7. 常见误区

⚠️ 误区 1:异常 = 代码写错了

语法错是编译错误,异常是运行时的意外——很多异常和"写错"无关:用户输错输入、要读的文件不存在、网络突然断了。异常是 Java 管理"计划外状况"的机制,不是丢人的标记。

⚠️ 误区 2:有问题编译器会报错提醒我

三大新手异常(空指针/越界/转型失败)全是 RuntimeException——编译器一个都不拦,全靠运行时才炸。编译通过 ≠ 运行没问题。

⚠️ 误区 3:红字打出来就完了,程序还会继续跑

异常若没人处理,当场中断——炸点之后的所有代码(哪怕逻辑完全无关)都不会执行。"只是控制台红了点"是最危险的错觉。

⚠️ 误区 4:Error 也是异常,也要处理

Error 和 Exception 是两兄弟:Error 是 JVM 级的严重错误(如内存耗尽),程序层面不该管也管不了。日常说的"异常处理"只针对 Exception 这一支。

⚠️ 误区 5:try-catch 是把错误藏起来

恰恰相反——它是把"意外"接住后体面处理:记日志、给用户友好提示、释放资源,然后让程序继续跑。不处理才是真把问题藏进了"程序崩溃"。下一节就学。

8. 自测题(先自己答,再展开)

❓ Q1:编译错误、异常、逻辑错误怎么区分?各举一例。

编译错误:编译期被拦,如少分号;异常:编译能过、运行时炸,如除零;逻辑错误:程序跑完结果不对,如把 > 写成 >=。前两种有报错可查,逻辑错误最阴险。

❓ Q2:异常在 Java 里的真身是什么?报告里装了哪三样信息?

是一个对象(异常类的实例,JVM 现场创建并抛出)。三样:异常类型(哪个类的对象)、异常消息(具体原因,如 / by zero)、发生位置(堆栈跟踪,类、方法、行号)。

❓ Q3:异常发生且没人处理,程序会怎样?

立即中断——异常抛出点之后的代码一行都不执行,报告打印到控制台。所以异常处理的真正目标不是"让报错好看",而是保证意外发生时程序能体面收场(释放资源、保存数据、给出提示)。

❓ Q4:Error 和 Exception 的区别?三大新手异常属于哪一支?

Error 是 JVM 级严重错误,管不了也不用管;Exception 是可处理的异常,是本章主角。三大新手异常(NPE / 越界 / ClassCastException)都是 Exception → RuntimeException 这一支的,特点是编译器不拦、运行时才炸。

❓ Q5(毕业题):读下面的报错,说出事故的全貌——
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Calc.divide(Calc.java:8)
    at Calc.main(Calc.java:3)

异常类型 ArithmeticException(算术异常),消息 / by zero(除数为零)。位置读法从上往下:直接炸点在 Calc.divide 第 8 行,它是被 main 第 3 行调用的——堆栈跟踪就是"事故现场的呼叫链",最上面一行是炸点本身,往下依次是"谁调出来的"。

9. 下一步学什么


相关笔记