Loading

有了 elseif 为什么还要 switch case

引出

你有没有想过既然有了if elseif, 为什么还要设计一个switch case的语法出来呢? 按理说, 一个语言的设计角度来说, 关键词越少越好吧, 而且多出来一种选择分支也没有看出太大用处. 以下几种switch case均可以写成if else的形式(java 代码):

// 形式一
switch(a){
  case 1:
    break;
  case 2:
    break;
  default:
    break;
}
if(a == 1){
}else if(a == 2){
}else{}

// 形式二
switch(a){
  case 1:
  case 2:
    //do something
    break;
  default:
    break;
}
if(a == 1 || a == 2){
}else{}
  

经过多次尝试, 所有的 switch case都可以转换成if else. 那当初涉及语言的大佬为什么要多此一举搞了这么一个switch case出来呢? 是何用意? 甚至还要加一个时不时就忘记的break.

分析

虽然我们已然回不到当初设计高级语言的哪个年代, 但是要继承胡先生的思想: "大胆假设, 小心求证".

为了了解为什么要设计出switch case, 就要先了解到它的特性, 借此来进一步推断设计的初衷, 亦或是弥补了if else的某些不足?

  1. switch case仅支持数字和字符串相等的判断, 甚至在 C 语言中只支持数字相等(其实其他语言也只支持数字, 随便写个 java 反编译一下就会发现, 它将一个switch case转成了两个, 一次字符串 hash 判断, 一次结果判断).
  2. switch case会跳转到符合条件的地方一直执行, 直到遇到break.

没了, switch case就这么点东西. 相比之下, 它只能做数字的相等校验, 比if else要笨的多, if else可以做所有的逻辑判断.

如果只能做数字的相等判断, 那么是不是可以将其想象成一个类似数组的结构, 可以直接以下标的形式进行索引, 而不是像if else要一个一个的进行判断呢? 没错, 事实上还真的是这样.

一个 switch case编译后的执行流程大致如下:

  • 将每一个 case编译后代码的首地址保存到一个数组中.
  • 根据传入的值进行判断, 若数据元素不存在, 直接跳到 default.
  • 若元素存在, 直接跳到索引处的地址继续执行.
  • 其中的break标志直接跳到结尾处.

画个简陋的图来对执行过程进行说明, 生成的索引数组中保存着对应跳转的具体地址, 然后直接进行数据的随机访问就可以完成比较了.

image-20200704001927028

看到这里, switch caseif else的区别呼之欲出了. switch case利用了数组的随机访问, 大幅度提升了判断的效率. 但是为了随机访问, 这里生成了一个中间数组来保存地址, 空间换时间.

总结

那么, 设想一下, 在最开始的语言设计时, 为什么要有switch case这种空间换时间的做法呢? 我猜, 可能是因为当时的 CPU 处理速度比较慢, 所以考虑到如此处理来令程序的运行速度加快. 亦或是最初的语言设计者为了追求完美, 将这种可加快条件判断的的语法也加进去了.

不过个人觉得, 如今的 CPU 运行速度已经如此速度了, 对于我们工作在应用层的人, 这点速度的影响应该是可以忽略不记的吧. 别说, 我试了几种比较流行的语言, 发现Python就不支持, 哈哈, 用了这么久Python还是突然发现它不支持switch case, 由此可见, switch case我用的比较少.

最后, 其实我就是好奇有了if else为什么还要设计个switch出来, 结果找着找着还真挺有意思的, switch的底层实现居然是数组的随机访问, 果然, 就不能想, 全是学问.

posted @ 2020-07-04 01:49  烟草的香味  阅读(457)  评论(0编辑  收藏  举报