小编典典

为什么我不能在字符串上使用 switch 语句?

all

这个功能会被放入更高版本的 Java 中吗?

有人可以解释为什么我不能这样做,例如 Javaswitch声明的技术方式吗?


阅读 145

收藏
2022-02-28

共1个答案

小编典典

带有 case 的 Switch 语句String已在Java SE
7
中实现,至少在它们首次被请求后 16
年。
没有提供延迟的明确原因,但可能与性能有关。

JDK 7 中的实现

该功能现在已javac
通过“脱糖”过程实现;String在声明中使用常量的干净的高级语法case在编译时扩展为遵循模式的更复杂的代码。生成的代码使用一直存在的
JVM 指令。

一个switchwith Stringcase
在编译期间被翻译成两个开关。第一个将每个字符串映射到原始开关中的唯一整数位置。这是通过首先打开标签的哈希码来完成的。对应的 case
是一个if测试字符串相等性的语句;如果散列上有冲突,则测试是级联的if-else- if。第二个开关反映了原始源代码中的内容,但将案例标签替换为其相应的位置。这个两步过程可以很容易地保留原始交换机的流量控制。

JVM 中的开关

有关更多技术深度switch,您可以参考 JVM 规范,其中描述了 switch
语句的编译
。简而言之,有两种不同的
JVM 指令可用于切换,具体取决于案例使用的常量的稀疏性。两者都依赖于对每种情况使用整数常量来有效执行。

如果常量是密集的,它们被用作索引(在减去最小值之后)到指令指针表(即指令)中tableswitch

如果常量是稀疏的,则执行正确大小写的二进制搜索——lookupswitch指令。

switch在对对象进行脱糖时String,可能会使用两个指令。适用于第lookupswitch一次打开哈希码找到机箱的原始位置。生成的序数自然适合
a tableswitch

两条指令都要求在编译时对分配给每种情况的整数常量进行排序。在运行时,虽然 的O(1)性能tableswitch通常看起来好于
O(log(n))性能lookupswitch,但需要进行一些分析以确定表是否足够密集以证明空间 - 时间折衷的合理性。Bill Venners
了一篇很棒的文章,更详细地介绍了这一点,并深入了解了其他
Java 流控制指令。

在 JDK 7 之前

在 JDK 7 之前,enum可以近似于String基于 -
的开关。这使用编译器在每种类型上生成的静态方法。valueOfenum例如:

Pill p = Pill.valueOf(str);
switch(p) {
  case RED:  pop();  break;
  case BLUE: push(); break;
}
2022-02-28