Java 12 switch表达式是返回值驱动的函数式新范式,必须穷尽所有分支、天然防穿透、编译期校验完备性;适用于输入到输出的确定性映射场景,如枚举转换、状态码计算等。

新 switch 表达式不是“更短的 switch 语句”,它是另一种编程范式:必须返回值、强制穷举、天然防漏,写错直接编译失败。
什么时候该用 switch 表达式而不是语句
当你需要把「输入 → 输出」映射成一个值时,比如转换枚举、格式化日志、计算状态码、构造 DTO 字段。它不适合做纯副作用操作(如调用 Console.WriteLine 后不返回任何东西)。
- 适合:
Direction.Up => Orientation.North、obj switch { string s => s.Length, int i => i * 2, _ => -1 } - 不适合:
case "log": Console.WriteLine("start"); break;—— 没返回值,编译报CS8506 - 若真要混副作用,得包装成 lambda 或提前
return,但会破坏表达式简洁性
switch 表达式必须覆盖所有可能输入
编译器会检查类型可穷举性。对 enum 类型,漏掉任意一个成员或没写 _ => ...,就报 CS8509;对 int 这类开放域类型,不写 _ => ... 直接编译失败。
- 正确(
enum+ 兜底):direction switch { Direction.Up => "N", Direction.Down => "S", _ => throw new ArgumentException() } - 错误(缺兜底):
direction switch { Direction.Up => "N", Direction.Down => "S" }→ 编译不过 - 对
object类型,_不够,还得处理null(null是独立模式,不被_匹配)
用好类型匹配 + when 守卫,别当 if 替代品
这是新版表达式真正省代码的地方:一次完成「判类型 + 解构变量 + 加条件」,避免 is/as 套娃和空引用风险。
- 传统写法易错:
if (obj is string && ((string)obj).Length > 0)—— 多余转换,且未处理null - 推荐写法:
obj switch { string s when s.Length > 0 => $"OK:{s}", int i when i > 100 => $"Big:{i}", null => "null input", _ => "other" } -
when后面是任意布尔表达式,支持方法调用、属性访问,但别放耗时逻辑——它在匹配路径上执行
常见编译错误和对应修复
遇到报错别急着改逻辑,先看是不是语法契约没满足:
-
CS8506(无最佳类型):某个分支返回void或类型不一致,比如有的返回string,有的返回int,确保所有分支类型可统一(或显式转成object) -
CS8509(未覆盖所有值):补全枚举项,或加_ => ...;注意nullable enum还要单独处理null -
CS8121(类型不匹配):比如对string输入写了int i => ...,模式和输入类型对不上
最常被忽略的是:空值不是万能兜底,null 和 _ 是两个独立模式,都要显式写。











