想象一下这个场景:你正在写一个水果识别的程序,用户输入「苹果」就要执行特定逻辑。在 Java 7 之前,你只能这样写:
这种写法就像超市收银员每次结账都要拆开包裹检查商品,而 Java 7 之后的字符串 switch 相当于给每个商品贴了快速识别条形码-程序员写代码更优雅。
以前为什么不能用字符串?
早期的 Java(Java 7 以前)switch 只能处理数字类数据(比如 int、char),因为这些类型底层可以直接用数字比对,简单快速。而字符串是复杂对象,直接逐个字符对比太费时间,所以那时候只能用 if-else 处理字符串分支。
字符串的“身份证”——哈希码(Hash Code)
每个字符串都有个唯一的哈希码(可以理解成根据内容用数学公式算出来的身份证号):
- • 比如 "苹果" 的哈希码是 12345,"香蕉" 的哈希码是 67890
- • 关键特性:内容相同的字符串哈希码一定相同,不同内容大概率不同(极小概率重复,叫“哈希碰撞”)
switch 字符串操作
1. 存身份证号编译器会把所有 case 后的字符串(比如 "苹果"、"香蕉")的哈希码存进一个数组里。
2. 先比身份证号运行到 switch 时,先计算输入字符串的哈希码(比如用户输入 "苹果",算出 12345),然后去数组里快速匹配。
3. 再验真身(防冒牌货)哈希码匹配后,还要用 equals() 方法确认字符串内容是否真的相同(防止极小概率的哈希碰撞)。
从本质来讲,switch 对字符串的支持,其实也是 int 类型值的匹配。
举个栗子 🌰
在这个例子中,编译器会先计算 "苹果" 和 "香蕉" 的哈希码,然后在运行时计算 fruit 的哈希码。如果 fruit 的哈希码和 "苹果" 的哈希码匹配,它会再用 equals 方法确认 fruit 是否真的是 "苹果"。如果是,就输出 "红富士"。
编译器的优化
为了让 switch 语句更高效,编译器还会做一些优化。比如,如果 case 标签不多,编译器可能会直接用一系列的 if-else 语句来代替 switch 语句。这样做可以减少 hashCode 计算和 equals 方法调用的次数,从而提高性能。
性能考虑
虽然字符串类型的 switch 语句很方便,但它毕竟需要计算哈希码 hashCode 和调用 equals 方法,所以在性能要求非常高的场合,可能不如用整数类型或枚举类型来得快。比如,在一些对速度要求极高的游戏中,开发者可能会选择用整数或枚举类型来避免额外的性能开销。switch 语句让编程变得更加灵活,但也需要注意它的性能特点,合理选择适用的场景。