Java switch从5到14逐步支持byte、short、char、int、enum(初始)、String(7+)、record和sealed类(14+表达式);不支持long、float、double、boolean及普通class。

switch 支持的类型从 Java 5 到 Java 14 的演进
Java 的 switch 语句不是一开始就支持所有类型的。早期只接受 byte、short、char、int 和它们对应的包装类,还有 enum —— 这些本质上都可隐式转为 int。
Java 7 开始支持 String,但要注意:它底层是通过 String.hashCode() + equals() 实现的,所以 null 会直接抛 NullPointerException。
Java 14 起引入了 switch 表达式(带 -> 和 yield),并允许 record 类型作为 case 值(前提是 record 的字段可被模式匹配识别);但普通语句形式的 switch 仍不支持 record 作为 case 标签值。
- ✅ 支持:
byte、short、char、int、enum、String(Java 7+) - ✅ Java 14+ 表达式中支持:
sealed类型的子类(配合模式匹配)、record(需配合case模式) - ❌ 不支持:
long、float、double、boolean、任意普通class实例(哪怕重写了equals)
String switch 的实际限制与坑点
虽然 String 看起来用起来像基本类型,但它有几处容易翻车:
立即学习“Java免费学习笔记(深入)”;
-
null传入会立即触发NullPointerException,且无法用case null:捕获(Java 21 才在 switch 表达式中支持case null ->) - 所有
case字符串必须是编译期常量(即字符串字面量或static final String),不能是运行时拼接的new String("abc")或方法返回值 - 大小写敏感,
"ABC"和"abc"是不同分支;没有内置忽略大小写的选项,得自己预处理 - 性能上,JVM 会对短字符串列表做哈希表跳转优化,但长列表(比如超 100 个 case)可能退化为 if-else 链,此时建议改用
Map查表
switch 表达式 vs 传统 switch 语句的关键区别
Java 14+ 的 switch 表达式(用 => 或 -> + yield)和老式语句行为差异很大,混用容易出错:
- 表达式必须穷尽所有可能(对
enum尤其严格),否则编译报错;而语句可以不写default - 表达式中每个
case分支默认不穿透(no fall-through),不需要break;语句中忘写break是经典 bug 来源 - 表达式支持多值
case:例如case "GET", "HEAD" -> doSomething();;语句中不支持这种写法 - 表达式可直接赋值:
String result = switch (method) { case "GET" -> "read"; default -> "unknown"; };;语句不行
为什么 long / double / boolean 依然不被支持
这不是 JVM 能力问题,而是设计取舍:
-
long:虽然能转成int截断,但会丢失精度,显式转换风险太大,JVM 宁愿不支持也不误导开发者 -
double/float:浮点数相等判断本身不可靠(NaN、精度误差),switch要求精确匹配,语义冲突 -
boolean:分支只有两个值,用if-else更自然;加进去反而让语法变臃肿,没实际收益 - 如果真要 switch
long,常见做法是转成String或拆成高低 32 位分别处理;但通常说明逻辑该重构了
真正需要多分支 dispatch 且类型不受限时,Map + 函数式接口(如 Function)或策略模式往往比硬塞 switch 更清晰、更易测、更易扩展。










