为什么我不能在String上使用switch语句?

4 浏览
0 Comments

为什么我不能在String上使用switch语句?

这个功能会在以后的Java版本中添加吗?

有人可以解释一下为什么我不能这样做,也就是Java的switch语句如何运作的技术方法吗?

admin 更改状态以发布 2023年5月23日
0
0 Comments

\n\n如果你的代码中有一个可以根据一个字符串进行切换的地方,那么重构这个字符串为可能的枚举值可能会更好,这样你可以将其用作切换条件。当然,你需要将可能的字符串值限制为枚举中的值,这可能是需要或不需要的。当然,你的枚举可以有一个\'其他\'的条目,并且有一个fromString(String)方法,然后你就可以有

ValueEnum enumval = ValueEnum.fromString(myString);
switch (enumval) {
   case MILK: lap(); break;
   case WATER: sip(); break;
   case BEER: quaff(); break;
   case OTHER: 
   default: dance(); break;
}

0
0 Comments

String类型的switch语句已经在Java SE 7中实现,这至少是在第一次请求之后的16年。没有明确的延迟原因,但这可能与性能有关。

JDK 7中的实现

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

带有String case的switch在编译时被翻译为两个switch。第一个将每个字符串映射到唯一的整数 - 它在原始switch中的位置。这是通过首先切换标签的哈希码来完成的。相应的case是一个测试字符串相等的if语句;如果哈希上有碰撞,则测试是一个级联的if-else-if。第二个switch反映了原始源代码中的switch,但用其对应的位置替换了case标签。这个两步过程使得很容易保留原始switch的流程控制。

JVM中的switch

有关switch的更多技术深度,您可以参考JVM规范,在其中描述了switch语句的编译。简而言之,取决于case使用的常量的稀疏程度,有两种不同的JVM指令可用于switch。两者都依赖于使用每个case的整数常量以有效地执行。

如果常量是密集的,则将它们用作索引(减去最低值后)到指令指针表中——tableswitch 指令。

如果常量是稀疏的,则执行针对正确情况的二分查找——lookupswitch 指令。

在对String对象执行switch时,这两个指令都可能会被使用。对于第一个在哈希码上的switch来找到原始位置,使用lookupswitch是适合的。得到的序数自然适合作为tableswitch

这两个指令都要求在编译时对每个case分配的整数常量进行排序。在运行时,虽然tableswitchO(1)性能通常优于lookupswitchO(log(n))性能,但需要进行一些分析以确定表是否足够密集以证明空间-时间的权衡。Bill Venners撰写了一篇名为“优化Java代码中'switch'语句的性能”的精彩文章,其中详细介绍了这一点,以及其他Java流控制指令的底层实现。

JDK 7之前

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

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

0