switchcase不能⽤静态常量’_Switch的内⼼世界
为什么要写这篇⽂章?
今⼉写代码时,⼀位前辈看到了我满篇的if+else if,他告诉我说:尽量使⽤switch来代替if+else if,if+else if效率⽐switch低,会增加⽆⽤的判断!
年轻的我差点就信了!
那么switch和if+else if的效率问题真的就如他所⾔?对我来说,这真的是个很有趣的问题!
同时我也想要知道,在我们实际开发中,什么时候⽤switch,什么时候⽤if+else if合适呢?
再后来,就引发了我更多的思考,switch它到底拿着我的判断条件是怎么操作的?
⼈年纪⼤了,什么都想问个为什么,这也是我想要写这篇⽂章的⼀个动机。
你有没有想过switch内部是怎样实现的?
就以下⼏种switch不同值的情况来进⾏分析吧!
1、switch的case值是连续的
我就先端⼀盘代码出来吧,switch的正常代码:
public class TestSwitch {
public int testSwitch(int t) {
int result= 0;
switch (t) {
case 0:
result= 100;
break;
case 1:
result= 200;
break;
case 2:
result= 300;
break;
}
return result;
}
}
这上⾯是⼀份很本分的switch代码,现在我们来看⼀下该代码在反汇编后的情况:
public class com.tang.demoapplication.TestPart.TestSwitch {
public com.tang.demoapplication.TestPart.TestSwitch();
Code:
0: aload_0 //将this引⽤推送⾄栈顶,即压⼊栈
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
public int testSwitch(int);
Code:
0: iconst_0
1: istore_2
2: iload_1
3: tableswitch { // A: 0 to 2 :从栈顶中弹出元素,检查是否在[0,2]之内
0: 28 //当code=0时,跳到28的位置,返回值100
1: 34 //当code=1时,跳到34的位置,返回值200
2: 41 //当code=2时,跳到41的位置,返回值300
default: 45 // B: 如果不在[0,2]内,则程序计数器跳转到第45⾏
}
28: bipush 100 //将常量100压⼊栈顶
30: istore_2 //将栈顶元素10存⼊局部变量表的第3个位置上
31: goto 45 //跳转到45⾏
34: sipush 200
37: istore_2 //将⼀个数值从操作数栈存储到局部变量表
38: goto 45
41: sipush 300
44: istore_2
45: iload_2
46: ireturn
}
你先记住上⾯这个 tableswitch ,它⾝上戏有点多。它要和下⾯的不连续的情况来进⾏对⽐,你才能更加深刻地感受到两者的差异!
2、switch的case值不是连续的
public class TestSwitch {
public int testSwitch(int t) {
int result = 0;
switch (t) {
case 0:
result = 100;
break;
case 4:
result = 200;
break;
case 9:
result = 300;
break;
}
return result ;
}
}
汇编结果:
public class com.tang.demoapplication.TestPart.TestSwitch {
public com.tang.demoapplication.TestPart.TestSwitch();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
public int testSwitch(int);
Code:
0: iconst_0
1: istore_2
2: iload_1
3: lookupswitch { //!!注意此时是lookupswitch
0: 36 //当值为0时,跳转到36⾏,返回值100
4: 42 //当值为4时,跳转到42⾏,返回值200
9: 49
default: 53
}
36: bipush 100
38: istore_2
39: goto 53
42: sipush 200
45: istore_2
46: goto 53
49: sipush 300
52: istore_2
53: iload_2
54: ireturn
}
(“上⾯是汇编,看不懂很正常!”,我⾃⾔⾃语道。)
好的,出现了,⼀个新名词:lookupswitch!
显⽽易见,当switch的值为有序的时候,⽤的是tableswitch;⽽当switch的值是⽆序的时候,⽤的是lookupswitch。tableswitch
lookupswitch
3、当switch的case类型为String
public class TestSwitch {
public int testSwitch(String t) {
int result = 0;
switch (t) {
case "a":
result = 100;
break;
case "d":
result = 200;
break;
case "f":
result = 300;
break;
}
return result ;
}
}
switch case判断字符串class编译结果:
public class TestSwitch {
public TestSwitch() {
}
public int testSwitch(String t) { int result = 0;
byte var4 = -1;
switch(t.hashCode()) {
case 97:
if (t.equals("a")) {
var4 = 0;
}
break;
case 100:
if (t.equals("d")) {
var4 = 1;
}
break;
case 102:
if (t.equals("f")) {
var4 = 2;
}
}
switch(var4) {
case 0:
result = 100;
break;
case 1:
result = 200;
break;
case 2:
result = 300;
}
return result ;
}
}
汇编结果:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论