java 7+ switch 支持 string,本质是编译器基于 hashcode() 和 equals() 生成跳转表;java 14+ 支持表达式形式,需用 -> 和 yield 或 default 穷尽覆盖,性能与语句版相当但更安全。

Java 的 switch 从 Java 7 开始支持 String,Java 14 起支持表达式形式(switch 表达式),但默认仍是语句;想用新特性得显式写 -> 分支且必须有 yield 或完整覆盖。
Java 7+ 怎么用 switch 处理字符串
本质是编译器把 String 的 hashCode() 和 equals() 编译成跳转表+校验,所以不是“直接比较引用”,也不是“反射或运行时解析”。
常见错误现象:NullPointerException(传入 null 时直接抛异常,不进任何 case);大小写敏感("A" 和 "a" 是不同分支)。
使用场景:配置项解析、协议类型分发、状态码映射等明确枚举值的字符串判断。
- 必须确保
case字面量是编译期常量(不能是new String("abc")) - 所有
case值会被自动去重,重复值编译报错 - 推荐加
default分支,避免漏处理未预期字符串
示例:
String action = "save";
switch (action) {
case "save":
doSave();
break;
case "delete":
doDelete();
break;
default:
throw new IllegalArgumentException("Unknown action: " + action);
}
Java 14+ switch 表达式怎么写才不报错
关键区别:语句版用 : + break,表达式版用 -> + yield(或单表达式自动返回),且必须穷尽所有可能(或带 default)。
常见错误现象:error: switch expression does not cover all possible input values(比如只写了几个 case 却没 default,而类型又不是 enum);yield 写成 return 或 break 直接编译失败。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
性能影响:表达式版在字节码层面仍生成跳转表,和语句版无实质差异;但强制穷尽性检查能提前暴露逻辑漏洞。
- 基本类型、
String、enum都可用,但非enum类型必须含default - 每个
case后只能跟一个表达式(如"ok"),或用{ }包裹多行并以yield结尾 - 不能混用
:和->,整块switch必须统一风格
示例:
String result = switch (status) {
case "pending" -> "waiting";
case "done" -> "success";
default -> "unknown";
};
为什么 switch 对 String 比 if-else 快(多数情况)
编译器对 String switch 做了优化:先比 hashCode(),再按哈希桶分组做 equals(),实际是“哈希表查找 + 短路校验”,而非逐个 equals()。
但这个优势只在 case 数 ≥ 5 左右才明显;太少时 if-else 反而更轻量。
- 如果字符串长度极短(如单字符),
if-else可能更快(避免哈希计算开销) - 若
case值存在明显概率分布(如 90% 是"get"),把高频值放前面的if-else更合适 - 注意:JIT 运行时可能进一步优化
if-else链,但switch的编译期结构更稳定
容易被忽略的兼容性细节
Java 7 支持 String switch,但不支持空字符串作为 case 值?错——空字符串完全合法,只是容易被误判为 null。
真正坑点在于:Android 开发中,即使设了 sourceCompatibility = JavaVersion.VERSION_11,旧版 Android Gradle Plugin 可能默认用 Java 8 编译,导致 switch 表达式语法不识别。
-
switch表达式是 Java 12 预览特性,Java 14 正式落地,需确认 JDK 版本 ≥ 14 且未禁用预览功能 - IDE(如 IntelliJ)可能默认启用新语法高亮,但构建工具(Maven/Gradle)的
maven-compiler-plugin版本太低会静默回退到语句模式 - 泛型类型擦除后无法
switch,例如switch ((String) obj)可以,但switch (obj)且obj是Object类型时,编译器无法推导,必须强转
事情说清了就结束。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










