📄 一句话概括
返回码每层都要判、漏一层就丢;异常中间两层一个字没写,错误直接穿到最外层。
📝 本节和前面几节的关系
4.15 管名字的边界,这一节管失败的边界。
一、返回码时代的麻烦
每层都要写 if err != OK: return err——写十层就写十遍。
漏一层,错误就被吞掉,程序带着坏数据继续跑。
更糟的是它把正常流程和错误处理搅在一起:读代码时分不清哪句是主逻辑。
二、实测穿透
level1 → level2 → level3,第三层 raise,最外层 try/except。
实测:最外层接住【第三层出错】,中间两层一个字都没写。
这就是异常和返回码的根本差别:错误能【跳】,不用一层层传。
三、它把两件事分开了
正常流程和错误处理被分到两个地方——这是【边界】这个词的确切含义。 主逻辑读起来是连续的,错误处理集中在能处理它的那一层。 所以异常不只是语法糖,它是一种结构:它规定了【谁负责收拾】。
四、代价
可能被吞:except: pass 会把错误彻底埋掉,比返回码漏判更难查。
开销略大:抛异常要收集栈信息,比 return 贵(虽然只在出错路径上)。
所以捕获要具体:不要一把抓 Exception,更不要空 except。
异常管的是【意外的失败】,不是【正常的分支】。拿它做流程控制,等于把边界又搅乱了。
五、动手 Demo:进化的 OOP 结构之二——异常
三层调用,最里面抛异常,中间两层什么都不写。 看错误能不能直接穿到最外层。
def level3():
raise ValueError("第三层出错")
def level2():
level3() # 不判、不传
def level1():
level2() # 不判、不传
try:
level1()
except ValueError as e:
print("在最外层接住:", e)
实跑输出:
--------------------------------------------------------------------
进化的 OOP 结构之二——异常
--------------------------------------------------------------------
没有异常的时代,错误靠**返回码**一层层往上传——**每层都要判,漏一层就丢。**
有异常之后,**错误可以【跳】到能处理它的那一层。**
level1 → level2 → level3(抛异常)
在最外层接住:**第三层出错**
实测:**中间两层一个字都没写,异常直接穿过去了。**
这在返回码时代是不可能的——**每层都得写 `if err != OK: return err`。**
返回码 异常
---------------------------------------------------------
每层要写吗 要 不用
漏判会怎样 错误被吞掉 不会,会一直冒泡
正常逻辑会不会被搅乱 会 不会
**注意最后一行**:返回码把【正常流程】和【错误处理】搅在一起,
**异常把它们分开了**——**这正是【边界】的意思。**
实测:中间两层一个字都没写,异常直接穿到最外层。 它把正常流程和错误处理分开了——这正是【边界】的意思;代价是可能被吞,所以捕获要具体。
30 秒实验
- 找一处空
except,判断它到底吞掉了什么。 - 把一段用返回码传错误的代码改成异常,看少写了几行。
常见误区
- 以为异常只是【另一种返回错误的方式】。它让错误能跳层。
- 以为捕获越多越安全。空 except 会把错误彻底埋掉。
自测三问(点开对答案)
1. 异常比返回码强在哪? —— 错误能跳层:中间层不用判、不用传,直接穿到能处理它的那一层——实测中间两层一个字都没写。 2. 异常把哪两件事分开了? —— 正常流程和错误处理——主逻辑连续,错误处理集中在能收拾的那一层。 3. 异常有什么代价? —— 可能被吞(空 except 比漏判更难查)、抛时要收集栈信息开销略大,所以捕获要具体。- ☐ 下一节(4.17 进化的OOP结构之三:垃圾回收)
相关笔记
- 进化的OOP结构之三:垃圾回收 — 第三条边界
- 更先进的OOP结构 — 三条边界的地图
- ☕ Java基础 · 索引 — 受检异常与运行时异常
- 🧩 面向对象是怎样工作的 · 索引