Otherwise,就是否则的意思。带入上下文也就是说前面的表达式是正常计算出来了一个东西了。
那么就拿着计算出来的这个东西(表达式的值)和每一个 case 里面的常量来对比,会出现以下的情况:
- 如果表达式的值和其中一个 case 语句中的常量相等了,那么我们就说 case 语句匹配上了。switch 代码块中匹配的 case 语句之后的所有语句 (如果有)就按照顺序执行。如果所有语句都正常完成,或者在匹配的 case 语句之后没有语句,那么整个 switch 代码块就将正常完成。
- 如果没有和表达式匹配的 case 语句,但是有一个 default 语句,那么 switch 代码块中 default 语句后面的所有语句(如果有)将按顺序执行。如果所有语句都正常完成,或者如果 default 标签之后没有语句了,则整个 switch 代码块就将正常完成。
- 如果既没有 case 语句和表达式的值匹配上,也没有 default 语句,那就没有什么搞的了,switch 语句执行了个寂寞,也算是正常完成。
其实到这里,上面的情况一不就是阿里巴巴 Java 开发手册的面试题的场景吗?
你看着代码,再看着翻译,仔细的品一品。
为什么那道面试题的输出结果是这样的:
没有为什么,Java 语言规范里面就是这样规定的,按照规定执行就完事了。
除了上面这三种流程,官网上还接着写了三句话:
如果 switch 语句块里面包含任何的表示或者意外导致立即完成的语句,则按如下方式处理:
我先说一下我理解的官方文档中说的:“any statement immediately ... completes abruptly”。
表示立即完成的语句就是每个 case 里面的 break、return。
意外导致突然完成的语句就是在 switch 语句块里面任何会抛出异常的代码。
如果出现了这两种情况,switch 语句块怎么处理呢?
如果语句的执行由于 break 语句而完成,则不会采取进一步的操作(进一步操作是指如果没有 break 代码,则将继续执行后续语句),switch 语句块将正常完成。
如果语句的执行由于任何其他原因突然完成(比如抛出异常),switch 语句块也会因相同的原因而立马完成。
上面就是 switch 语句的执行流程。所以你还别觉得 switch 语句就必须要个 break,别人的设计就是如此,看场景的。
比如看官方给出的两个示例代码:
这是不带 break 的。需求就要求这样输出,你整个 break 干啥。
再看另外一个带 break 的:
实现的又是另外一个需求了。
所以,看场景。
另外,我觉得官网上的这个例子给的不好。最后少了一个 default 语句。看看阿里 Java 开发手册上怎么说的:
这个地方见仁见智吧。
底层技术实现
第二个考点是底层技术实现。
也就下面这坨代码:
前面讲了哈,官方文档里面有这样的一句话:
规定如此。
所以,这小节的答案是这样的吗?肯定不是的,我们多想一步:
为什么这样规定呢?
这才是这小节想要带大家寻找的东西。
首先你得知道 switch 支持 String 是 Java 的一颗语法糖。既然是语法糖, 我们就看看它的 class 文件:
从 class 文件中,我们尝到了这颗语法糖的味道。原来实际上是有两个 switch 操作的。
switch 支持 String 类型的原因是先取的 String 的 hashCode 进行 case 匹配,然后在每个 case 里面给 var3 这个变量赋值。然后再对 var3 进行一次 switch 操作。
所以,上图中标记的 15 行,如果 String 是 null,那么对 null 取 hashCode ,那可不得抛出空指针异常吗?
所以,你看《Java开发手册》里面的这个建议:
明白为什么这样写了吧?
所以,这小节的答案是这样的吗?肯定不是的,我们再多想一步呢:
为什么要非得把 String 取 hashCode 才进行 switch/case 操作呢?
从 class 文件中我们已经看不出什么有价值的东西了。只能在往下走。
class 再往下走就到哪里了?
对了,需要看看字节码了。
通过 javap 获得字节码文件:
这个字节码很长,大家自己编译后去看一下,我就不全部截取,浪费篇幅了。
在这个字节码里面,就算你什么都不太明白。但是只要你稍微注意一点点,你应该会注意到其中的这两个地方: