switch 语句(基础)
本教程共 93 篇 · 第 22 篇 · 更新于 2026-08-08 · 约 8 分钟阅读
本节目标:掌握 switch 的基本结构,理解“必须穷尽所有情况”和“匹配即结束、不会掉进下一个 case”这两条核心规则。
if 适合处理两三个分支。一旦要判断的情况变多,一长串 else if 会又臭又长。Swift 的 switch 就是为这种“多分支按值匹配”的场景准备的,而且它比 C、Java 里的 switch 强得多。基础章节先把骨架搭好,进阶章节再上威力更大的匹配模式。
1-1 switch 长什么样
switch 后面跟一个要被检查的值,花括号里是一个个 case。每个 case 写一个或一组可能匹配的值,命中后就执行对应的代码。
let someCharacter: Character = "z"
switch someCharacter {
case "a":
print("拉丁字母的第一个")
case "z":
print("拉丁字母的最后一个")
default:
print("其他字符")
}
这里 someCharacter 是字符 "z",依次和各个 case 比较,命中 case "z" 就打印对应内容。switch 走完就结束,不会继续往后跑。读起来就像在说“这个值,是 a 就怎样,是 z 就怎样,否则怎样”。
1-2 必须穷尽:所有情况都得有人接
这是 Swift switch 最重要的一条铁律:必须穷尽(exhaustive)。也就是说,被检查的值所有可能的结果,都得被某个 case 覆盖到。
上面的例子里,字符远不止 a 和 z。所以不能只写这两个 case,必须加一个 default 来兜住其余所有情况。default 用关键字 default 表示,而且必须放在最后。
如果忘写 default,或者某个可能的值没被覆盖,编译器会直接报错,不让你跑。这其实是好事——它强迫你在写代码时就想清楚“剩下的情况怎么办”,而不是等到运行时才措手不及。很多运行时崩溃,根子就是当初漏考虑了某种输入。
Note当你匹配的是枚举(后面会讲),而枚举的每个成员都写了
case,就可以不写default,因为枚举本身就穷尽了。但匹配Int、String、字符这类开放类型时,default几乎总是必需的。
1-3 没有隐式贯穿:命中即结束
如果你写过 C 或 Objective-C,会记得每个 case 末尾得写 break,否则会“贯穿”到下一个 case。Swift 完全反过来:默认不会贯穿。
只要第一个匹配的 case 执行完,整个 switch 就结束了,不需要写 break。这让代码更安全,也避免了手滑同时跑了多个分支。C 里忘记写 break 是经典 bug,Swift 从语言层面消灭了它。
let anotherCharacter: Character = "a"
let message = switch anotherCharacter {
case "a":
"拉丁字母的第一个"
case "z":
"拉丁字母的最后一个"
default:
"其他字符"
}
print(message)
这是 switch 的“表达式”形式:每个 case 直接写一个值,整体结果赋给 message。和 if 表达式一样,它要求每个分支产出同类型的值。表达式形式和语句形式你都会见到,本质相同,只是表达式能直接当值用。
1-4 每个 case 不能为空
Swift 不允许出现空的 case。下面这种写法会编译报错:
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a": // 错误:这个 case 体是空的
case "A":
print("字母 A")
default:
print("不是字母 A")
}
编译器会告诉你 case "a": 里没有任何可执行的语句。它这么做是为了防止你误以为 "a" 和 "A" 会一起命中——在 Swift 里它们不会。想让一个 case 同时匹配多个值,要用下面说的复合写法。
1-5 复合 case:一个分支匹配多个值
想让一个分支同时接住 "a" 和 "A",用逗号把值列在一起,这就是“复合 case”。
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
print("字母 A")
default:
print("不是字母 A")
}
值之间用逗号分隔,命中其中任意一个就执行该分支。值多的时候也能写成多行,可读性更好:
let vowel: Character = "e"
switch vowel {
case "a", "e", "i", "o", "u":
print("\(vowel) 是元音")
default:
print("\(vowel) 不是元音")
}
Tip复合 case 是“或”的关系:匹配清单里任意一个即可。它和
if里的逻辑或||思路一致,只是写在了switch里更整齐,尤其当清单较长时优势明显。
1-6 想忽略某个 case 时用 break
前面说 Swift 不需要 break。但在一种情况下你会用到它:刻意匹配某个 case 却什么都不做,纯粹为了“表明我考虑过这种情况”。
let numberSymbol: Character = "三"
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
possibleIntegerValue = 1
case "2", "٢", "二", "๒":
possibleIntegerValue = 2
default:
break
}
这里 default 分支什么都不用做,于是只写一个 break。注意:只写注释不算语句,编译器仍会报空 case 错误,所以必须用 break 来占位。break 在这里的作用就是“匹配到了,但立即结束 switch”。
1-7 和 if 该怎么选
粗略的经验:if 适合判断“一个条件成立不成立”,尤其条件是基于范围或布尔逻辑时。switch 适合“这个值等于哪些离散的可能”,分支多的时候最清爽。
比如判断分数是“优秀、良好、及格、不及格”,用 switch 配区间(下一章会讲)就很顺;判断“是否成年”这种单一布尔条件,用 if 更直接。两者并非互斥,熟练之后你会凭直觉在两者间切换。
1-8 switch 和枚举是天生一对
等你学到枚举(enum)会发现,switch 和它配合最默契。枚举的成员是有限的、已知的,比如表示方向的 north、east、south、west。当你为枚举的每个成员都写了一个 case,编译器就能确认已经穷尽,于是连 default 都不用写。
反过来,如果哪天你给枚举加了一个新成员,却忘了在 switch 里加对应分支,编译器会直接报错提醒你。这种“编译器兜底”的特性,让 switch 成为处理枚举的首选方式,也是 Swift 类型安全的重要体现。
1-9 编译器替你查漏
穷尽性检查发生在编译阶段,不是运行时。也就是说,漏掉的情况在你还没跑程序时就被拦下了。这比靠测试去碰运气可靠得多。
写 switch 时不用怕分支多,反而应该欢迎分支多——把每种情况摊开写清楚,编译器帮你看着有没有遗漏。这也是 Swift 强调“能在编译期发现的错误,就不要留到运行时”的一贯风格。把判断逻辑显式写出来,既方便编译器检查,也方便后来的人读。
理解了基础结构,switch 真正的威力还在后面——区间匹配、元组、值绑定、where 子句,下一章接着讲。这些进阶玩法才是 Swift switch 甩开其他语言的地方。
学完这章你可以做件小事巩固一下:找一个原来用 if-else 链写的判断,试着改写成 switch。改写过程中你会真切体会到“穷尽性”带来的安全感——编译器不再让你漏情况,漏了它当场报错。下一章我们把区间、元组这些更强的模式加上去,那时你会发现 switch 能表达的东西远比一堆等号比较要丰富。