异常章五节串成一条线:看见事故 → 分清责任 → 掌握对策 → 懂得甩锅 → 印自己的事故报告——从"怕报错"到"会安排后事",程序从此炸得体面。
1. 五节串成一条线
| 节 | 主题 | 一句话收网 |
|---|---|---|
| 5.1 | 什么是异常 | 异常 = 运行时的意外;异常对象 = 事故报告(类型/消息/位置),不处理就当场中断 |
| 5.2 | 两派异常 | 划分标准是"怪谁"不是"谁严重":自己的 bug 改代码(运行时),外部风险写预案(编译时) |
| 5.3 | 处理语法 | 一组接(try/catch/finally)一组甩(throw/throws);安检从 println"贴告示"升级为 throw"拉闸" |
| 5.4 | 抛出异常 | throw 后方法非正常中断;异常沿甩锅链条层层上溯,最终接住或甩给 JVM |
| 5.5 | 自定义异常 | 继承 + throw 的组合技:印一张说行话的事故报告,catch 精准分诊 |
暗线:程序对"意外"的态度在升级——5.1 只会看(读报错)→ 5.3 学会接(换备胎)→ 5.4 学会甩(免责声明)→ 5.5 学会造(分诊系统)。这一章之后,你的程序从"一炸就死"变成"炸了也有安排"。
2. 核心概念速查(12 条,考前 3 分钟扫完)
| # | 概念 | 一句话 |
|---|---|---|
| 1 | 异常 | 运行时意外,本质是 JVM 现场 new 出来的对象 |
| 2 | 异常对象三要素 | 类型(什么事故)+ 消息(details)+ 位置(堆栈跟踪) |
| 3 | Throwable 家谱 | Error(管不了,不碰)和 Exception(主角)两支 |
| 4 | 运行时异常 | RuntimeException 子孙,unchecked,编译器放行 |
| 5 | 编译时异常 | 受检 checked,编译器逼你 try-catch 或 throws |
| 6 | try-catch | try 监控,catch 接住;炸点后 try 剩余代码不跑 |
| 7 | finally | 收尾专用,两条路都跑,return 拦不住(System.exit 除外) |
| 8 | catch 规矩 | 类型要接得住;多 catch 命中即走;子类在前父类殿后 |
| 9 | throw | 方法体内动作,跟异常对象;甩出后方法非正常中断 |
| 10 | throws | 方法签名声明,跟类名可多个;只是免责转嫁 |
| 11 | 甩锅链条 | 没 catch 的方法自动上溯,main 也不接 → 甩给 JVM → 中断 |
| 12 | 自定义异常 | 继承 Exception/RuntimeException + super(message) 传消息 |
3. 代码模板速查(四段,背熟能救命)
模板一:标准接法(try-catch-finally)
try {
// 风险代码(越小越好,只包会炸的)
} catch (具体异常类型 e) {
// 接住后的预案:提示 / 换默认值 / 记日志
} finally {
// 收尾:无论如何都要做的事(关资源等)
}
模板二:安检甩出(throw + throws)
public void setAge(int age) throws AgeOutOfBoundsException {
if (age < 0 || age > 150) {
throw new AgeOutOfBoundsException("年龄 " + age + " 不合法");
}
this.age = age;
}
模板三:自定义异常类(背下这个骨架)
public class XxxException extends Exception { // 业务风险选 Exception
public XxxException() { super(); }
public XxxException(String message) { super(message); } // 忘了这行 → getMessage() 为 null
}
模板四:完整闭环(甩 + 接 + 取消息)
try {
p.setAge(-5);
} catch (AgeOutOfBoundsException e) {
System.out.println("安检拦截:" + e.getMessage());
}
4. 本章名坑回顾(七个,个个真会撞)
- catch 父类在前 → 后面的子类 catch 永远够不着,编译直接报"已捕获"。
- try 包太大 → 语法不错但炸了之后 try 剩余全跳过,本来不想连坐的也连坐了。
- catch (Exception e) 一把梭 → 什么都能接 = 什么都分不清,信息全被抹平。
- return 拦不住 finally → 就算 catch 里 return,finally 也先跑完才走。
- throw 后写代码 → unreachable statement,编译报错(方法已经非正常中断了)。
- 忘 super(message) → 消息断传,
getMessage()返回 null。 - 重写方法 throws 更大 → 只能比父类小或相等——"编译看左"的延伸,子类不能甩出新锅。
5. 异常章收官:一条安检演进线
3.3 println 贴告示 → 只提示不拦人,错误数据照样进对象
5.3 throw Exception → 拉闸了,但全场都说"普通话",分不清事故类型
5.5 自定义异常 → 每种业务问题一张专属报告,catch 精准分诊 ✅
异常处理是封装的最后一块拼图:setter 里藏安检、安检用异常表达、异常用继承分类——面向对象的三大特性(封装/继承/多态)在异常这一章全部实战了一遍。
6. 与前面章节的连线(复习用)
- 4.1 继承 → 异常家谱全靠 extends 挂枝叶,自定义异常就是新枝叶
- 4.4 多态 →
catch (Exception e)能接住它所有子孙,"父类引用指子类对象"又上岗 - 4.8 本章小结 → 三大特性收官后,异常章把封装补完整
- 第一章 Java开发入门/1.4 Java程序的运行机制 → 编译期 vs 运行期两道关,正是 5.2 两派划分的底层依据
- 3.4 构造方法 → super(message) 把消息上交父类存档,就是构造方法链条
7. 毕业自检(5 题,合上笔记答)
运行时(unchecked)编译器挥手放行:NullPointerException、ArrayIndexOutOfBoundsException;编译时(checked)当场拦下逼写预案:ParseException、ClassNotFoundException。划分标准是"怪谁":使用者的 bug vs 外部环境风险。
子类在前、父类殿后。父类在前时子类 catch 永远执行不到,编译器直接报错"已捕获该异常"。本质是 catch 按家谱匹配,父类型能接住子类型(多态)。
throw 是方法体里的动作:throw new XxxException("..."),真把异常对象甩出去,方法从此非正常中断;throws 是方法签名上的声明:void f() throws XxxException,告知调用者"我可能甩这种锅,你表态"。
构造方法里漏了 super(message)——消息没上交父类存档,detailMessage 还是空的。补上那行就通。
public class BalanceNotEnoughException extends Exception {
public BalanceNotEnoughException(String message) { super(message); }
}
public void withdraw(double amount) throws BalanceNotEnoughException {
if (amount > balance) throw new BalanceNotEnoughException("余额不足:当前 " + balance);
balance -= amount;
}
main 里 try { acc.withdraw(500); } catch (BalanceNotEnoughException e) { System.out.println(e.getMessage()); }——余额不足是业务风险(外部风险型),所以继承 Exception 走受检待遇。
8. 下一步学什么
- ☑ 6.1 包装类 ✅ —— 第六章「Java API」开课:8 大基本类型的对象外衣,4.5 谜底正式收网。点此复习
相关笔记
- 第五章 异常/5.5 自定义异常类 ← 上一篇:异常章最后一块拼图
- 第四章 面向对象(下)/4.8 本章小结:上一章小结,三大特性进度条在那点亮
- 第五章 异常/5.1 什么是异常:本章起点,事故报告与家谱的出处
- 00-索引:全书篇目总表