引出
你有没有想过既然有了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
的某些不足?
switch case
仅支持数字和字符串相等的判断, 甚至在 C 语言中只支持数字相等(其实其他语言也只支持数字, 随便写个 java 反编译一下就会发现, 它将一个switch case
转成了两个, 一次字符串 hash 判断, 一次结果判断).switch case
会跳转到符合条件的地方一直执行, 直到遇到break
.
没了, switch case
就这么点东西. 相比之下, 它只能做数字的相等校验, 比if else
要笨的多, if else
可以做所有的逻辑判断.
如果只能做数字的相等判断, 那么是不是可以将其想象成一个类似数组的结构, 可以直接以下标的形式进行索引, 而不是像if else
要一个一个的进行判断呢? 没错, 事实上还真的是这样.
一个 switch case
编译后的执行流程大致如下:
- 将每一个
case
编译后代码的首地址保存到一个数组中. - 根据传入的值进行判断, 若数据元素不存在, 直接跳到 default.
- 若元素存在, 直接跳到索引处的地址继续执行.
- 其中的
break
标志直接跳到结尾处.
画个简陋的图来对执行过程进行说明, 生成的索引数组中保存着对应跳转的具体地址, 然后直接进行数据的随机访问就可以完成比较了.
看到这里, switch case
和if else
的区别呼之欲出了. switch case
利用了数组的随机访问, 大幅度提升了判断的效率. 但是为了随机访问, 这里生成了一个中间数组来保存地址, 空间换时间.
总结
那么, 设想一下, 在最开始的语言设计时, 为什么要有switch case
这种空间换时间的做法呢? 我猜, 可能是因为当时的 CPU 处理速度比较慢, 所以考虑到如此处理来令程序的运行速度加快. 亦或是最初的语言设计者为了追求完美, 将这种可加快条件判断的的语法也加进去了.
不过个人觉得, 如今的 CPU 运行速度已经如此速度了, 对于我们工作在应用层的人, 这点速度的影响应该是可以忽略不记的吧. 别说, 我试了几种比较流行的语言, 发现Python
就不支持, 哈哈, 用了这么久Python
还是突然发现它不支持switch case
, 由此可见, switch case
我用的比较少.
最后, 其实我就是好奇有了if else
为什么还要设计个switch
出来, 结果找着找着还真挺有意思的, switch
的底层实现居然是数组的随机访问, 果然, 就不能想, 全是学问.