为什么我们需要在 case 语句之后break?
为什么编译器不自动在 switch 中的每个代码块后面放置break语句?是因为历史原因吗?你什么时候想要执行多个代码块?
Why doesn't the compiler automatically put break statements after each code block in the switch? Is it for historical reasons? When would you want multiple code blocks to execute?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
有时,将多个案例与同一代码块相关联会很有帮助,例如
等。仅举一个例子。
根据我的经验,通常“失败”并为一种情况执行多个代码块是不好的风格,但在某些情况下可能会有用处。
Sometimes it is helpful to have multiple cases associated with the same code block, such as
etc. Just an example.
In my experience, usually it is bad style to "fall through" and have multiple blocks of code execute for one case, but there may be uses for it in some situations.
历史上,这是因为
case
本质上定义了一个标签
,也称为goto 的目标点调用。 switch 语句及其关联的情况实际上只是表示一个多路分支,具有代码流中的多个潜在入口点。
话虽如此,人们已经无数次注意到,
break
几乎总是您希望在每种情况结束时都采用的默认行为。Historically, it's because the
case
was essentially defining alabel
, also known as the target point of agoto
call. The switch statement and its associated cases really just represent a multiway branch with multiple potential entry points into a stream of code.All that said, it has been noted a nearly infinite number of times that
break
is almost always the default behavior that you'd rather have at the end of every case.Java 源自 C,这就是 C 的语法。
有时您希望多个 case 语句只有一个执行路径。
下面的示例将告诉您一个月中有多少天。
Java comes from C and that is the syntax from C.
There are times where you want multiple case statements to just have one execution path.
Below is a sample that will tell you how many days in a month.
你可以通过案例失败做各种有趣的事情。
例如,假设您想要对所有情况执行特定操作,但在特定情况下您想要执行该操作以及其他操作。使用带有 drop-through 的 switch 语句会使事情变得非常容易。
当然,很容易忘记 case 末尾的
break
语句并导致意外的行为。当您省略break语句时,好的编译器会警告您。You can do all sorts of interesting things with case fall-through.
For example, lets say you want to do a particular action for all cases, but in a certain case you want to do that action plus something else. Using a switch statement with fall-through would make it quite easy.
Of course, it is easy to forget the
break
statement at the end of a case and cause unexpected behavior. Good compilers will warn you when you omit the break statement.switch
case
之后的break
用于避免 switch 语句中的失败。有趣的是,现在可以通过 JEP-325 实现的新形成的开关标签来实现这一点。通过这些更改,可以避免每个开关
case
的break
,如进一步演示的:-On 使用 JDK-12 执行上述代码,比较输出可以被视为
并且
当然事情没有改变
The
break
after switchcase
s is used to avoid the fallthrough in the switch statements. Though interestingly this now can be achieved through the newly formed switch labels as implemented via JEP-325.With these changes, the
break
with every switchcase
can be avoided as demonstrated further :-On executing the above code with JDK-12, the comparative output could be seen as
and
and of course the thing unchanged
撇开能够在多种情况下使用相同的块(可能是特殊情况)的良好愿望......
它主要是为了与 C 兼容,可以说是很久以前
goto
关键字在地球上流行的一种古老的技巧。当然,它确实实现了一些令人惊奇的事情,例如Duff 的设备 ,但无论这是赞成还是反对,充其量只是争论而已。Leaving aside the good desire to be able to use the identical block for several cases (which could be special-cased)...
It's mainly for compatibility with C, and is arguably an ancient hack from the days of old when
goto
keywords roamed the earth. It does enable some amazing things, of course, such as Duff's Device, but whether that's a point in its favor or against is… argumentative at best.因此,如果您需要多个案例来执行同一操作,则不必重复代码:
或者您可以执行以下操作:
以级联方式。
如果你问我的话,真的很容易出现错误/混乱。
So you do not have to repeat code if you need several cases to do the same thing:
Or you can do things like :
In a cascade fashion.
Really bug/confusion prone, if you ask me.
就历史记录而言,Tony Hoare 在 20 世纪 60 年代“结构化编程”革命期间发明了 case 语句。 Tony 的 case 语句支持每个 case 多个标签,并且自动退出,没有令人讨厌的
break
语句。对显式break
的要求源自 BCPL/B/C 行。 Dennis Ritchie 写道(在 ACM HOPL-II 中):我还没有找到任何关于 BCPL 的历史著作,但 Ritchie 的评论表明
中断
或多或少是一个历史意外。 BCPL 后来解决了这个问题,但也许 Ritchie 和 Thompson 太忙于发明 Unix,无暇顾及这样的细节:-)As far as the historical record goes, Tony Hoare invented the case statement in the 1960s, during the "structured programming" revolution. Tony's case statement supported multiple labels per case and automatic exit with no stinking
break
statements. The requirement for an explicitbreak
was something that came out of the BCPL/B/C line. Dennis Ritchie writes (in ACM HOPL-II):I haven't been able to find any historical writings about BCPL, but Ritchie's comment suggests that the
break
was more or less a historical accident. BCPL later fixed the problem, but perhaps Ritchie and Thompson were too busy inventing Unix to be bothered with such a detail :-)Java 源自 C,其遗产包括名为 Duff's Device 的技术。
这是一种优化,它依赖于这样一个事实:在没有
break;
语句的情况下,控制权会从一种情况转移到另一种情况。当 C 被标准化时,已经有大量类似“野外”的代码,而改变语言来破坏此类结构会适得其反。Java is derived from C, whose heritage includes a technique known as Duff's Device .
It's an optimization that relies on the fact that control falls through from one case to the next, in the absence of a
break;
statement. By the time C was standardized, there was plenty of code like that "in the wild", and it would have been counterproductive to change the language to break such constructions.正如人们之前所说,它是允许失败的,这不是一个错误,而是一个特性。
如果太多
break
语句让您烦恼,您可以使用return
语句轻松摆脱它们。这实际上是一个很好的实践,因为你的方法应该尽可能小(为了可读性和可维护性),所以switch
语句对于一个方法来说已经足够大了,因此,一个好的方法不应包含任何其他内容,这是一个示例:执行打印:
如预期。
As people said before, it is to allow fall-through and it is not a mistake, it is a feature.
If too many
break
statements annoy you, you can easily get rid of them by usingreturn
statements instead. This is actually a good practice, because your methods should be as small as possible (for the sake of readability and maintainability), so aswitch
statement is already big enough for a method, hence, a good method should not contain anything else, this is an example:The execution prints:
as expected.
这是一个老问题,但实际上我今天遇到了使用没有break语句的情况。当你需要按顺序组合不同的函数时,不使用break实际上非常有用。
例如,使用http响应代码通过时间令牌服务器响应代码401来验证用户
-令牌已过时->重新生成令牌并登录用户。
服务器响应代码 200 - 令牌正常 -> log user in.
in case 语句:
使用此功能,您不需要为 401 响应调用 log in user 函数,因为重新生成令牌时,运行时会跳转到 case 200。
It is an old question but actually I ran into using the case without break statement today. Not using break is actually very useful when you need to combine different functions in sequence.
e.g. using http response codes to authenticate user with time token
server response code 401 - token is outdated -> regenerate token and log user in.
server response code 200 - token is OK -> log user in.
in case statements:
Using this you do not need to call log in user function for 401 response because when the token is regenerated, the runtime jumps into the case 200.
如果编译器没有添加自动中断,则可以通过从 1 和 2 中删除 break 语句,使用 switch/case 来测试
1 <= a <= 3
等条件。Not having an automatic break added by the compiler makes it possible to use a switch/case to test for conditions like
1 <= a <= 3
by removing the break statement from 1 and 2.因为在某些情况下,您希望流过第一个块,例如以避免在多个块中编写相同的代码,但仍然能够将它们分开以进行更多控制。还有很多其他原因。
because there are situations where you want to flow through the first block for example to avoid writing the same code in multiple blocks but still be able to divide them for mroe control. There are also a ton of other reasons.
您可以轻松分离其他类型的数字、月份、计数。
在这种情况下,这会更好;
You can makes easily to separate other type of number, month, count.
This is better then if in this case;
我现在正在开发一个项目,我需要在 switch 语句中使用
break
,否则代码将无法工作。请耐心听我说,我会给你一个很好的例子来说明为什么你的 switch 语句中需要break
。想象一下,您有三种状态,一种状态等待用户输入数字,第二种状态计算该数字,第三种状态打印总和。
在这种情况下,您可以:
查看状态,您希望提取顺序从 state1 开始,然后是 state3,最后是 state2。否则我们只会打印用户输入而不计算总和。为了再次澄清,我们等待用户输入一个值,然后计算总和并打印总和。
下面是一个示例代码:
如果我们不使用
break
,它将按照 state1、state2 和 state3 的顺序执行。但是使用break
,我们可以避免这种情况,并且可以按照正确的过程进行排序,即从 state1 开始,然后是 state3,最后但并非最不重要的 state2。I am now working on project where I am in need of
break
in my switch statement otherwise the code won't work. Bear with me and I will give you a good example of why you needbreak
in your switch statement.Imagine you have three states, one that waits for the user to enter a number, the second to calculate it and the third to print the sum.
In that case you have:
Looking at the states, you would want the order of exaction to start on state1, then state3 and finally state2. Otherwise we will only print users input without calculating the sum. Just to clarify it again, we wait for the user to enter a value, then calculate the sum and prints the sum.
Here is an example code:
If we don't use
break
, it will execute in this order, state1, state2 and state3. But usingbreak
, we avoid this scenario, and can order in the right procedure which is to begin with state1, then state3 and last but not least state2.确实如此,因为通过一些巧妙的放置,您可以级联执行块。
Exactly, because with some clever placement you can execute blocks in cascade.