使用箭头(->)来编写Switch表达式,现在可以返回值。

6
在Java 14中新增了扩展的switch表达式,除了提高程序员/代码审查者的视觉清晰度外,对于switch表达式的需求不是很明确。以下是需要解答的问题:
  1. 它与旧版本的switch表达式相比是否是一种不同的字节码实现?
  2. 在执行方面是否有性能改进?
参考:https://www.techgeeknext.com/java/java14-features JDK 14版本:
 int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};

JDK 14 - 字节码

   0: iconst_1
   1: istore_1
   2: iload_1
   3: tableswitch   { // 1 to 7
                 1: 44
                 2: 44
                 3: 44
                 4: 49
                 5: 54
                 6: 54
                 7: 59
           default: 64
      }
  44: bipush        6
  46: goto          65
  49: bipush        7
  51: goto          65
  54: bipush        8
  56: goto          65
  59: bipush        9
  61: goto          65
  64: iconst_0
  65: istore_2
  66: return

JDK - 10代码

int numLetters;
int day = 1;
switch (day) {
  case 1:
  case 2:
  case 3:
    numLetters = 6;
    break;
  case 4:
    numLetters = 7;
    break;
  case 5:
  case 6:
    numLetters = 8;
    break;
  case 7:
    numLetters = 9;
    break;
  default:
    numLetters = 0;
}

JDK - 10 字节码

   0: iconst_1
   1: istore_2
   2: iload_2
   3: tableswitch   { // 1 to 7
                 1: 44
                 2: 44
                 3: 44
                 4: 50
                 5: 56
                 6: 56
                 7: 62
           default: 68
      }
  44: bipush        6
  46: istore_1
  47: goto          70
  50: bipush        7
  52: istore_1
  53: goto          70
  56: bipush        8
  58: istore_1
  59: goto          70
  62: bipush        9
  64: istore_1
  65: goto          70
  68: iconst_0
  69: istore_1
  70: return

对于原语类型,除了块内的局部赋值减少了JIT指令外,没有什么主要区别。


你自己尝试过找到答案了吗? - Ronald
JEP(JDK增强提案):https://openjdk.java.net/jeps/361 - Jatish
1
@Ronald,我已经编辑了问题中的细节,这是我研究过的内容。 - Jatish
1
好的,通过你已经展示的编辑,你已经发现字节码略有不同。从性能的角度来看,两者并没有太大的区别。在Java10中,执行的语句数量为8个(0、1、2、3、44、46、47、70),而在Java14中只有7个(0、1、2、3、44、46、66)。很可能是tableswitch(3)语句比较耗费资源。因此,我预计会有几个百分点的性能提升。(将两个变量在一个循环中执行100,000次,并测量时间)。 - Ronald
当我在这里使用原始类型(int)并且选择是静态的 - day = 1 的值时,没有主要的性能改进。我已经执行了循环“20亿+次”。执行时间如下:JDK-14 - 3317.8微秒和JDK 10 - 3343.200微秒。 - Jatish
显示剩余3条评论
1个回答

6

就像使用 Stringswitch 一样,字节码没有改变,也没有必要改变。

虽然字节码最初是专门为编译Java源代码而设计的目标,但它并没有受到同样的限制。另请参见Java语言中不可用的字节码特性...

switch表达式利用了一项以前普通Java代码未使用的功能,但肯定被自动代码生成器或编译器用于针对JVM的其他编程语言,即在switch分支中将值推送到操作数栈中,在合并点后使用。对于老旧的switch语句,您总是需要将该值存储到本地变量中,并在合并点后加载它。

〈另一个未被普通Java代码利用的特性,但与Java字节码兼容的是,通过在switch指令之前设置目标位置(们),滥用switch指令来生成花式循环。谁知道将来的某个语言版本是否会利用这个特性...〉

但是,无论是否使用中间本地变量都不应该有太大影响。优化器将代码转换为SSA形式后,所有在本地变量和操作数堆栈之间的传输都将在应用其他代码转换和优化之前消除。

这并不排除由于特定实现(版本)中switch指令的微妙更改而导致的性能差异


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接