We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
编译器会使用tableswitch和lookup指令来生成Switch语句的编译代码,并且都只能支持int类型的条件值.因此byte,char,short类型的值都会被向上拓展为int类型。
tableswitch的做法是直接将条件值和case进行一一比较,整个操作为O(1),因此非常快。 例如下面这段代码
int chooseNear(int i) { switch (i) { case 0: return 0; case 1: return 1; case 2: return 2; default: return -1; } }
可以发现,case分支的条件值很紧凑,中间没有断层,编译后的代码为:
tableswitch 1 3 OneLabel TwoLabel ThreeLabel default: DefaultLabel
但是如果中间有断层的话,编译器会进行一些优化,看这段代码:
switch (inputValue) { case 1: // ... case 3: // ... case 4: // ... case 5: // ... default: // ... }
这段代码可以说近乎是紧凑的,只有2是缺少的,编译代码如下:
tableswitch 1 6 OneLabel FakeTwoLabel ThreeLabel FourLabel FiveLabel default: DefaultLabel ; ...... FakeTwoLabel: DefaultLabel: ; default code
可以看到编译器为‘2’这种情况,自动生成了一个虚假的case:FakeTwoLabel,而当执行到case 2的时候,会自动跳转到default的处理代码。
lookupswitch是对索引表中的键进行比较,如果条件值和某个键匹配,则跳转到这个键对应的分支偏移量继续执行,若没有键值符合,那么就执行default处理代码段。而且键值必须是排序过的,这样将会比线性查找效率好很多,例如采用二分查找,效率为O(log n)。 下面这段代码,case的条件值很分散,有上百个断层,因此编译器也必须生成上百个fake case,结果会生成一个超大的table,class文件的大小爆炸式增长,这种做法显然不符合现实,因此编译器会生成一段lookupswitch指令
switch (inputValue) { case 1: // ... case 10: // ... case 100: // ... case 1000: // ... default: // ... }
编译后的代码为:
lookupswitch 1 : Label1 10 : Label10 100 : Label100 1000 : Label1000 default : DefaultLabel
这个表只有五项,4个真实的值,如果采用二分查找,log4=2,JVM至多只需要2次就可以找到结果。就算表有100项,也才比较7次左右好么。
tableswitch用于case比较紧凑的代码,而lookup用于case比较分散的代码。如果不考虑空间的话,tableswitch指令比lookup指令有更高的执行效率。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
编译Switch语句
编译器会使用tableswitch和lookup指令来生成Switch语句的编译代码,并且都只能支持int类型的条件值.因此byte,char,short类型的值都会被向上拓展为int类型。
TableSwitch
tableswitch的做法是直接将条件值和case进行一一比较,整个操作为O(1),因此非常快。
例如下面这段代码
可以发现,case分支的条件值很紧凑,中间没有断层,编译后的代码为:
但是如果中间有断层的话,编译器会进行一些优化,看这段代码:
这段代码可以说近乎是紧凑的,只有2是缺少的,编译代码如下:
可以看到编译器为‘2’这种情况,自动生成了一个虚假的case:FakeTwoLabel,而当执行到case 2的时候,会自动跳转到default的处理代码。
lookupswitch
lookupswitch是对索引表中的键进行比较,如果条件值和某个键匹配,则跳转到这个键对应的分支偏移量继续执行,若没有键值符合,那么就执行default处理代码段。而且键值必须是排序过的,这样将会比线性查找效率好很多,例如采用二分查找,效率为O(log n)。
下面这段代码,case的条件值很分散,有上百个断层,因此编译器也必须生成上百个fake case,结果会生成一个超大的table,class文件的大小爆炸式增长,这种做法显然不符合现实,因此编译器会生成一段lookupswitch指令
编译后的代码为:
这个表只有五项,4个真实的值,如果采用二分查找,log4=2,JVM至多只需要2次就可以找到结果。就算表有100项,也才比较7次左右好么。
结论
tableswitch用于case比较紧凑的代码,而lookup用于case比较分散的代码。如果不考虑空间的话,tableswitch指令比lookup指令有更高的执行效率。
The text was updated successfully, but these errors were encountered: