#1 楼
有时将多个案例与同一代码块关联会很有帮助,例如case 'A':
case 'B':
case 'C':
doSomething();
break;
case 'D':
case 'E':
doSomethingElse();
break;
等。只是一个例子。
以我的经验,通常“摔倒”并在一种情况下执行多个代码块是不好的风格,但是在某些情况下可能有用。 />
评论
只需始终添加注释//故意掉线。当您忽略休息时。在我看来,这并不是一个糟糕的风格,而是“容易忘记意外中断”。附言当然,在简单的情况下,答案并不像答案本身那样。
–双重
2010-4-25 23:04
@doublep-我同意。我认为,如果可能的话,我会避免这样做,但是如果有意义,那么请确保您正在做的事情非常清楚。
–野生甲壳动物
2010-4-25在23:08
@doublep:如果多个case那样堆叠在一起,我不会理会注释。如果它们之间有代码,则是,可能值得评论。
–比利·奥尼尔
2010-4-26的3:13
我想象一种语言,您可以在一个案例中声明多个案例,例如:case'A','B','C':doSomething(); case'D','E':doSomethingElse();,而无需在大小写之间进行中断。 Pascal可以这样做:“ case语句将序数表达式的值与每个选择器进行比较,选择器可以是常量,子范围或用逗号分隔的列表。” (wiki.freepascal.org/Case)
–克里斯蒂安·塞姆劳(Christian Semrau)
2011年8月4日在21:33
#2 楼
从历史上看,这是因为case
本质上定义了label
,也称为goto
调用的目标点。 switch语句及其相关案例实际上只是代表一个多路分支,其中有多个潜在的入口点进入代码流。所有这些,已经注意到
break
几乎是无数次。总是在每种情况下都希望使用的默认行为。#3 楼
Java来自C,这就是C的语法。有时您希望多个case语句只有一个执行路径。
下面的示例将告诉您有多少个示例一个月内的天数。
class SwitchDemo2 {
public static void main(String[] args) {
int month = 2;
int year = 2000;
int numDays = 0;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
if ( ((year % 4 == 0) && !(year % 100 == 0))
|| (year % 400 == 0) )
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}
System.out.println("Number of Days = " + numDays);
}
}
评论
有人瞄准了向上箭头而错过了吗?或者也许他们吃了带有您的支撑风格或压痕的牛肉...
–吉姆·刘易斯
2010-4-25 23:27
Dunno,所以请给我+1。尽管我真的希望Java选择了一个更现代的case语句,但是这是一个可以提供帮助的示例。 Cobol的EVALUATE-WHEN-OTHERWISE功能强大得多,并且早于Java。 Scala的match表达式是可以做什么的现代示例。
– Jim Ferrans
2010-4-25 23:29
我的学生会因为这样做而被公开招致。土狼丑陋。
– ncmathsadist
2014年9月9日14:16
@ncmathsadist它说明了一种做某事的方式。我不同意这个例子可能是极端的。但这是一个真实的例子,我相信它可以帮助人们理解一个概念。
–罗曼·希波(Romain Hippeau)
2014年9月9日15:21
#4 楼
我认为这是一个错误。作为一种语言构造,将break
设置为默认值,而使用fallthrough
关键字则一样容易。在每种情况下,我编写和阅读的大多数代码都会中断。评论
我宁愿建议继续
– Vilx-
2010年4月26日在9:21
@Vilx当在当前开关中允许任意大小写时,这简单地变成了goto。 ;-)
–克里斯蒂安·塞姆劳(Christian Semrau)
11年8月4日在21:28
#5 楼
您可以通过案例执行各种有趣的操作。例如,假设您想针对所有案例执行特定的操作,但是在某些情况下您想要执行该操作,其他的东西。switch (someValue)
{
case extendedActionValue:
// do extended action here, falls through to normal action
case normalActionValue:
case otherNormalActionValue:
// do normal action here
break;
}
当然,很容易忘记案件末尾的
break
语句并引起意外行为。当您省略break语句时,好的编译器会警告您。 评论
可以在Java中的字符串上使用switch / case吗?
–郭富城
2010-4-26在2:58
@Steve:糟糕,我想现在不行。根据stackoverflow.com/questions/338206/…,在将来的Java版本中将允许使用字符串。 (我目前使用C#进行大部分编程,但确实允许在switch语句中使用字符串。)我已经编辑了答案,以消除误导性的引号。
–扎克·约翰逊(Zach Johnson)
2010-4-26的3:13
@ZachJohnson,很久以后,Java 7确实允许打开Strings。
–鲍勃·克罗斯(Bob Cross)
2013年6月5日15:30
#6 楼
为什么编译器不自动在开关中的每个代码块之后放置break语句?
抛弃了在几种情况下能够使用相同块的良好愿望(可能是特例)...
是出于历史原因吗?什么时候要执行多个代码块?
主要是为了与C兼容,并且可以说是
goto
关键字在地球上漫游时的古老黑客。当然,它确实启用了一些令人惊奇的功能,例如Duff的设备,但这是赞成还是反对这一观点……充其量是有争议的。#7 楼
开关break
之后的case
用于避免switch语句中的失败。尽管有趣的是,现在可以通过通过JEP-325实现的新形成的开关标签来实现。 通过这些更改,可以避免带有每个开关
break
的case
,如进一步说明:-public class SwitchExpressionsNoFallThrough {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int value = scanner.nextInt();
/*
* Before JEP-325
*/
switch (value) {
case 1:
System.out.println("one");
case 2:
System.out.println("two");
default:
System.out.println("many");
}
/*
* After JEP-325
*/
switch (value) {
case 1 ->System.out.println("one");
case 2 ->System.out.println("two");
default ->System.out.println("many");
}
}
}
在使用JDK执行上述代码时-12,比较输出可以看作是
//input
1
// output from the implementation before JEP-325
one
two
many
// output from the implementation after JEP-325
one
和
//input
2
// output from the implementation before JEP-325
two
many
// output from the implementation after JEP-325
two
当然是这样不变
// input
3
many // default case match
many // branches to 'default' as well
#8 楼
因此,如果您需要几种情况来做相同的事情,则不必重复代码:case THIS:
case THAT:
{
code;
break;
}
也可以执行以下操作:
case THIS:
{
do this;
}
case THAT:
{
do that;
}
以层叠的方式。
如果您问我,确实很容易出现错误/混乱。
评论
既可以做到这一点,也可以做到这一点,但是只是做到这一点?
–JonnyRaa
14年8月27日在16:08
只需阅读文档即可。那是糟糕的!编写错误的简便方法!
–JonnyRaa
14年8月27日在16:12
#9 楼
就历史记录而言,托尼·霍尔在1960年代“结构化程序设计”革命期间发明了案例说明。 Tony的case语句每个案例支持多个标签并自动退出,而不会发臭break
语句。对明确的break
的要求是来自BCPL / B / C系列的。 Dennis Ritchie(在ACM HOPL-II中)写道:例如,当我们在1960年代,所以break关键字的重载以逃避B和C switch语句是由于发散的进化而不是有意识的变化。
我还没有能够找到有关BCPL的任何历史著作,但Ritchie的评论表明
break
或多或少是一次历史性事故。 BCPL后来解决了这个问题,但也许Ritchie和Thompson太忙于发明Unix了,所以不愿被这样的细节困扰:-) 评论
这应该获得更多选票。显然,OP已经知道省略中断可以“执行多个代码块”,并且更关心这种设计选择的动机。其他人提到了从C到Java的著名传承,而这一答案将研究推向了C之前。我希望我们从一开始就具有这种(虽然非常原始的)模式匹配。
–wlnirvana
3月6日13:18
#10 楼
Java是从C派生的,C的遗产包括称为Duff的设备的技术。优化是基于这样的事实,即在没有
break;
语句的情况下,控制权从一种情况转移到另一种情况。到C标准化时,已经有很多类似“狂野”的代码,因此更改语言以破坏这种构造可能会适得其反。 #11 楼
正如人们之前所说,这是允许失败,这不是错误,这是一个功能。如果太多
break
语句使您烦恼,则可以使用return
语句轻松摆脱它们。这实际上是一个好习惯,因为您的方法应尽可能小(出于可读性和可维护性的考虑),因此switch
语句对于一个方法而言已经足够大,因此,一个好的方法不应包含任何其他内容,这是一个示例:public class SwitchTester{
private static final Log log = LogFactory.getLog(SwitchTester.class);
public static void main(String[] args){
log.info(monthsOfTheSeason(Season.WINTER));
log.info(monthsOfTheSeason(Season.SPRING));
log.info(monthsOfTheSeason(Season.SUMMER));
log.info(monthsOfTheSeason(Season.AUTUMN));
}
enum Season{WINTER, SPRING, SUMMER, AUTUMN};
static String monthsOfTheSeason(Season season){
switch(season){
case WINTER:
return "Dec, Jan, Feb";
case SPRING:
return "Mar, Apr, May";
case SUMMER:
return "Jun, Jul, Aug";
case AUTUMN:
return "Sep, Oct, Nov";
default:
//actually a NullPointerException will be thrown before reaching this
throw new IllegalArgumentException("Season must not be null");
}
}
}
执行打印:
12:37:25.760 [main] INFO lang.SwitchTester - Dec, Jan, Feb
12:37:25.762 [main] INFO lang.SwitchTester - Mar, Apr, May
12:37:25.762 [main] INFO lang.SwitchTester - Jun, Jul, Aug
12:37:25.762 [main] INFO lang.SwitchTester - Sep, Oct, Nov
如预期。
#12 楼
编译器未添加自动中断功能,因此可以通过从1和2中删除break语句来使用开关/情况来测试类似1 <= a <= 3
的条件。switch(a) {
case 1: //I'm between 1 and 3
case 2: //I'm between 1 and 3
case 3: //I'm between 1 and 3
break;
}
评论
是的。我完全讨厌这个。
– ncmathsadist
2014年9月9日14:15
#13 楼
因为在某些情况下,您希望流经第一个块,例如,避免在多个块中编写相同的代码,但仍然可以将它们分割以进行mroe控制。还有很多其他原因。#14 楼
这是一个老问题,但实际上我今天遇到了没有中断声明的情况。当您需要按顺序组合不同的功能时,不使用break实际上非常有用。例如使用http响应代码对具有时间令牌的用户进行身份验证
服务器响应代码401-令牌已过时->重新生成令牌并登录用户。
服务器响应代码200-令牌正常->日志用户输入。
万一语句:
case 404:
case 500:
{
Log.v("Server responses","Unable to respond due to server error");
break;
}
case 401:
{
//regenerate token
}
case 200:
{
// log in user
break;
}
使用此方法,您无需为401响应调用登录用户功能,因为当令牌被重新生成,运行时跳入案例200。
#15 楼
您可以轻松地将其他类型的数字,月份,计数分开。在这种情况下,这会更好;
public static void spanishNumbers(String span){
span = span.toLowerCase().replace(" ", "");
switch (span){
case "1":
case "jan": System.out.println("uno"); break;
case "2":
case "feb": System.out.println("dos"); break;
case "3":
case "mar": System.out.println("tres"); break;
case "4":
case "apr": System.out.println("cuatro"); break;
case "5":
case "may": System.out.println("cinco"); break;
case "6":
case "jun": System.out.println("seis"); break;
case "7":
case "jul": System.out.println("seite"); break;
case "8":
case "aug": System.out.println("ocho"); break;
case "9":
case "sep": System.out.println("nueve"); break;
case "10":
case "oct": System.out.println("diez"); break;
}
}
#16 楼
我现在在我的switch语句中需要break
的项目上工作,否则代码将无法工作。忍受我,我会给你一个很好的例子,说明为什么在switch语句中需要break
。 假设您有三种状态,一种等待用户输入数字,第二种进行计算,第三种打印总和。
在这种情况下,您具有:
状态1-等待用户输入数字
状态2-打印sum
state3-计算总和
查看状态,您可能希望精确的顺序从state1开始,然后是state3,最后是state2。否则,我们将仅打印用户输入而不计算总和。只是为了再次澄清一下,我们等待用户输入一个值,然后计算总和并打印总和。
以下是示例代码:
while(1){
switch(state){
case state1:
// Wait for user input code
state = state3; // Jump to state3
break;
case state2:
//Print the sum code
state = state3; // Jump to state3;
case state3:
// Calculate the sum code
state = wait; // Jump to state1
break;
}
}
如果我们不使用
break
,它将按以下顺序执行:state1,state2和状态3。但是使用break
,我们避免了这种情况,并且可以按照正确的顺序进行命令,该过程以state1开始,然后是state3,最后但并非最不重要的是state2。
评论
回答了有关JDK-12的问题,并对开关标签进行了重新设计,以确保不强制中断。