问题描述
在 Java 和 Eclipse (Kempler) 的最新稳定版本中,输入以下代码并执行,假设包名和类名存在:
In the latest stable release of Java and Eclipse (Kempler), entering the following code and executing it, assuming the package and class names exist:
package some_package; public class what_the_heck { public static void main(String[] args) { int p = 2; int x = 1; switch(p){ case (1): x--; case (2): x = 2; case (3): x = 3; default: x++; } System.out.println(x); } }
这会打印值 4.本来我认为它应该打印 2,因为我认为即使没有 break 语句,每段代码仍然保存在一个 case 语句中.现在我认为问题在于它是如何编译的.例如,我目前的信念是,在内部,布尔值会跟踪 case 语句是否等于该值.如果是,则布尔值为真,所有 case 语句都将被视为真,直到找到中断.这是有道理的,但我仍然想知道这背后是否还有其他原因,或者我的假设是否完全错误.
This prints the value 4. Originally, I thought it should print 2 because I thought that even if there were no break statements, each piece of code is still held in a case statement. Now I think that the issue lies in how it is compiled. For example, my current belief is that internally a boolean keeps track of whether or not a case statement was equal to the value. If it was, then the boolean is true and all case statements will be treated as true until a break is found. This makes sense, but I am still wondering if there are other reasons behind this, or if I am entirely wrong in my assumption.
推荐答案
switch之所以会这样,是因为:
The reason why switch works as it does is that this:
switch(p){ case (1): x--; case (2): x = 2; case (3): x = 3; default: x++; }
实际上只是这个的语法糖(基本上):
is really just syntactic sugar for this (basically):
if (p == 1) goto .L1; else if (p == 2) goto .L2; else if (p == 3) goto .L3; else goto .L4; .L1: x--; .L2: x = 2; .L3: x = 3; .L4: x++;
Java 没有 goto 语句,但 C 有,这就是它的来源.因此如果 p 为 2,它会跳转到 .L2 并执行该标签后面的所有语句.
Java doesn't have a goto statement, but C does, and that's where it comes from. So if p is 2, it jumps to .L2 and executes all the statements following that label.