javaswitch性能_JavaSwitch语句及性能剖析(转载补充)switch的case语句可以处理int,short,byte,char类型的值,但是不能处理long,String等类型。
因为short,byte,char都会转换成int进⾏处理,这⼀点也可以从⽣成的字节码看出。
char a = 'e';
switch (a) {
case 'c':
System.out.println("In case c");
break;
case 'd':
System.out.println("In case d");
break;
default:
System.out.println("In default");
break;
case 'e':
System.out.println("In case e");
break;
}
0:  bipush  101
2:  istore_1
3:  iload_1
switch case判断字符串4:  tableswitch{ //99 to 101
99: 32;
100: 43;
101: 65;
default: 54 }
⽣成的字节码始终为bipush或iconst(⼩于5的整数),⽤于将整数压⼊栈。
⼆、新特性
在JDK 5中加⼊的枚举Enum类型也是可以作为case值的。
Type t = Type.C;
switch (t) {
case A:
System.out.println("In case A");
break;
System.out.println("In case B");
break;
default:
System.out.println("In default");
break;
case C:
System.out.println("In case C");
break;
}
0:  getstatic      #18; //Field com/cdai/jdk/Type.C:Lcom/cdai/jdk/Type;
3:  astore_1
4:  invokestatic    #24; //Method $SWITCH_TABLE$com$cdai$jdk$Type:()[I
7:  aload_1
8:  invokevirtual  #27; //Method com/cdai/dinal:()I
11:  iaload
12:  tableswitch{ //1 to 3
1: 40;
2: 51;
3: 73;
default: 62 }
从字节码可以看出,对于枚举类型也是调⽤它的ordinal⽅法转成整型后进⾏switch匹配的。
在JDK 7中,⼜加⼊了对String类型的⽀持,从此不⽤再写If-Else来判断字符串了。
三、两种字节码
switch语句有两种编译结果:
当case中的值连续时,编译成tableswitch,解释执⾏时从table数组根据case值计算下标来取值,从数组中取到的便是要跳转的⾏数。
int a = 1;
switch (a) {
case 2:
System.out.println("In case 2");
break;
case 3:
System.out.println("In case 3");
default:
System.out.println("In default");
break;
case 1:
System.out.println("In case 1");
break;
}
0:  iconst_1
1:  istore_1
2:  iload_1
3:  tableswitch{ //1 to 3
1: 61;
2: 28;
3: 39;
default: 50 }
28:  getstatic      #16; //Field java/lang/System.out:Ljava/io/PrintStream;
31:  ldc    #22; //String In case 2
33:  invokevirtual  #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
36:  goto    69
39:  getstatic      #16; //Field java/lang/System.out:Ljava/io/PrintStream;
42:  ldc    #30; //String In case 3
44:  invokevirtual  #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
47:  goto    69
50:  getstatic      #16; //Field java/lang/System.out:Ljava/io/PrintStream;
53:  ldc    #32; //String In default
55:  invokevirtual  #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
58:  goto    69
61:  getstatic      #16; //Field java/lang/System.out:Ljava/io/PrintStream;
64:  ldc    #34; //String In case 1
66:  invokevirtual  #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
当case中的值不连续时,编译成lookupswitch,解释执⾏时需要从头到尾遍历到case对应的代码⾏。因为case对应的值不是连续的,如果仍然⽤表来保存case对应的⾏号,会浪费⼤量空间。
int a = 10;
switch (a) {
case 2:
System.out.println("In case 2");
break;
case 3:
System.out.println("In case 3");
break;
default:
System.out.println("In default");
break;
case 10:
System.out.println("In case 10");
break;
}
0:  bipush  10
2:  istore_1
3:  iload_1
4:  lookupswitch{ //3
2: 40;
3: 51;
10: 73;
default: 62 }
40:  getstatic      #16; //Field java/lang/System.out:Ljava/io/PrintStream;
43:  ldc    #22; //String In case 2
45:  invokevirtual  #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 48:  goto    81
51:  getstatic      #16; //Field java/lang/System.out:Ljava/io/PrintStream;
54:  ldc    #30; //String In case 3
56:  invokevirtual  #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 59:  goto    81
62:  getstatic      #16; //Field java/lang/System.out:Ljava/io/PrintStream;
65:  ldc    #32; //String In default
67:  invokevirtual  #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 70:  goto    81
73:  getstatic      #16; //Field java/lang/System.out:Ljava/io/PrintStream;
76:  ldc    #34; //String In case 10
78:  invokevirtual  #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
由此可以看出,这两种编译结果是编译器在考虑空间占⽤情况下,对代码效率进⾏的优化。
另外需要注意⼀点,就是不管是tableswitch还是lookupswitch,default标签都放在最后进⾏匹配,但下⾯各个case和default语句块的顺序是与源代码相同的。所以尽管default标签没有放在最后,
但它仍然是最后被匹配的。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。