switch语句原理及易错点

不加break会怎样

观察下面的代码:
在这里插入图片描述
第一段代码是最常见的写法,也是最好的写法,约定俗成的每个条件语句后添加break。如果因为某种原因没有写break语句,没有对此情况进行过探究的话,可能还真不知道第二、三段代码会输出什么。

结论:如果不加break,程序从匹配成功的case语句开始,一直到遇见break语句或者执行完成所以条件语句块后才会跳出判断,不管后面的case语句是否匹配成功都会执行语句块中的代码,也就是上面的第二、三段代码。

有时候会故意缺省break语句来达到某种效果(例如几种判断都执行相同的代码块),不过这种情况极少,比如下面这个并没有太大意义的例子,当检测到当前月份是1、2、3、4月时都会输出“现在是第一季度”:

switch (month){
    case 1:
    case 2:
    case 3:
    case 4:
        System.out.println("现在是第一季度");
        break;
    default:
        break;
}

switch语句的原理

根据经验,当switch语句和if…else if…else语句可以实现相同功能(并且分支较多)时会尽量使用switch语句,因为switch语句的效率更高。

if…else if…else语句的执行方式是顺序执行所有判断语句,直到满足条件时执行语句代码块。

switch语句会维护一张跳转表,不管case判断语句的值是不是按照顺序的,内存中的地址表都会按照顺序进行排列。

switch语句会生成一个跳转表来指示实际的case分支的地址,而这个跳转表的索引号与switch变量的值是相等的。从而,switch-case不用像if-else if那样遍历条件分支直到命中条件,而只需访问对应索引号的表项从而到达定位分支的目的。 具体地说,switch-case会生成一份表项数为case量+1的跳表,程序首先判断switch变量是否大于(小于)最大(最小)case 常量,若大于(小于),则跳到default分支处理;否则取得索引号为switch变量大小的跳表项的地址(即跳表的起始地址+表项大小*索引号),程序接着跳到此地址执行,到此完成了分支的跳转。

case判断的条件会有下面几种情况,对应switch语句中的执行过程是不一样的:
1、case条件的值是连续的,例如:case 1、case 2、case 3、case 4、case 5
  在switch中,编译器多增加了一个数组用于存储每个case对应的地址,根据switch中传入的整数在数组中查到到对应的地址,直接通过这个地址跳转到对应的位置。编译器在处理switch时会首先校验不满足所有case的情况,当这种情况发生时代码调转到default或者switch语句块之外。然后将传入的整数值减一(数组元素是从0开始计数)。最后根据参数值找到应该跳转的位置。
在这里插入图片描述
2、case条件的值不是连续的,例如:case 1、case 2、case 3、case 5
  去除掉上面的case 4条件后,仍会建立一个表,对应下图中的关系。
在这里插入图片描述
3、case条件的值不是连续的,例如:case 1、case 2、case 5、case 6、case 256
  如果case条件间的值差异较大,则编译器会采用索引表的方式来进行地址的跳转,对应下图中的关系。
在这里插入图片描述
如果想对内存进行深入研究的话可以编写demo对内存进行跟踪,下面这两篇文章描述的也比较详细:https://www.cnblogs.com/mukekeheart/p/10558167.html、https://www.jianshu.com/p/d382f653dd00

性能优化

  • 因为if…else if…else语句会逐个条件进行判断,直到命中,所以应将机率大的条件置于前面,这样可以减少比较的次数
  • 如果分支较少,比如小于4个,或者case语句判断的值跳跃较大时,没必要使用switch语句
  • 编译器是根据时间和空间的消耗来决定那种方式效率更高,所以在Switch写判断条件的时候最好做到连续紧密,可以最大限度的节省时间和内存

switch语句的注意事项

  • 当遇到 break 语句时,switch 才会终止,控制流将跳转到 switch 语句后的下一行
  • Java中的switch语句中表达式的值必须是整型、字符型、字符串类型(JDK7添加的新特性)和枚举类型
    引申:case语句后常量表达式的值绝不可以是实数(有限小数、无限小数),例如case 1.1:即为不合法语句
  • C++中的switch语句中表达式的值必须是整型、字符型和枚举类型,不能是字符串类型
  • switch语句与其他控制语句的一个不同点:每个case中的多条语句加不加大括号均可
  • 最好在switch中添加default语句,用来处理异常情况
发布了48 篇原创文章 · 获赞 100 · 访问量 26万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章