开关表达式(JEP 361)
Java从第一个发行候选版本开始就有switch语句。 Switch的现有实现遵循过程语言(C和C ++)的设计和语法,并且默认情况下支持语义分解。
开关的典型实现如下所示:
private static int existingSwitchWithDefault(DAY day){int numberOfCharacters = 0;switch(day){case MONDAY:case FRIDAY:numberOfCharacters = 6;break;case TUESDAY:numberOfCharacters = 7;break;case WEDNESDAY:numberOfCharacters = 9;break;case THURSDAY:case Saturday:numberOfCharacters = 8;break;default:throw new IllegalArgumentException("Invalid input "+day+" provided.");}return numberOfCharacters;
}
现有switch语句存在一些问题:
- 默认掉线
像其他过程语言一样,switch语句支持默认掉线。 它是一把双刃剑,有时有用,但通常很危险,并且是一个讨厌的地方,可以隐藏虫子。
在上面的示例中,如果开发人员错过投放**打破**并编写这样的代码
private static int existingSwitchWithBug(DAY day){int numberOfCharacters = 0;switch(day){case WEDNESDAY:numberOfCharacters = 9; // Missed a break FALL THROUGHcase THURSDAY:numberOfCharacters = 8;break;}return numberOfCharacters;
}
方法将被称为“** existingSwitchWithBug(DAY.WEDNESDAY)” **由于掉线,它将返回8而不是9。 如果没有适当的单元测试,这种错误很难发现。
- 默认不是
如果开发人员调用上述方法(例如“** existingSwitchWithBug(DAY.MONDAY)**”将仅返回0。这可能是有效的业务案例,但大多数情况下会发生这种情况,因为开发人员忘记在switch语句中涵盖所有必需的案例。
如果编译器强制在switch语句中强制使用默认大小写,这不好吗?
- 太冗长
在每种情况下都有break语句会使switch语句读起来很冗长,并且绝对是隐藏错误的地方。
What is Switch Expression?
Switch表达式作为JDK 12中的JEP 325的预览功能发布(在本JEP中**打破**根据社区的反馈(开发人员发现使用break从switch表达式返回感到困惑)被超载以从switch表达式返回结果),新的JEP 325(引入新的语句yield来返回并恢复break的原始含义)是 介绍了使用JDK 13实现并作为预览功能发布的功能。
开关表达式作为JDK 14的标准功能发布。
在继续前进之前,了解语句和表达之间的区别很重要。 表达式的值是一个值(您可以将其打印或分配给变量),而语句则执行某项操作,表示一个动作或命令(否则或循环)
如果您还记得上面提到的switch语句示例,则可以使用如下的switch表达式编写相同的示例:
private static int withSwitchExpression(String day){int result = switch (day){case "Monday","Friday" -> 6;case "Tuesday" ->7;case "Wednesday" ->9;case "Thursday" ->8;default -> throw new IllegalStateException("Unexpected value: " + day);};return result;
}
以上片段中需要注意的几件事:
- 一种新形式的开关标签,“case L ->”,表示如果标签匹配,则仅执行标签右边的代码。 右边的代码“case L ->”只能是表达式,块或throw语句。如果标签匹配,则仅执行箭头右侧的表达式或语句;否则,将不执行任何操作。没有失败。Switch语句已扩展,因此可以用作表达式,请记住上述语句和表达式之间的区别。如果使用switch表达式,则需要一个默认情况来强调所有可能的情况,如果使用Enum作为案例标识符,则可以跳过默认情况,编译器可以查看是否覆盖了所有情况
下面的代码是完全可以的,不会有任何编译时错误
switch(day){case MONDAY,FRIDAY,SUNDAY -> 6;case TUESDAY -> 7;case WEDNESDAY -> 9;case THURSDAY,SATURDAY -> 8;
};
yield
到现在为止,我们看到了一个示例,其中开关表达式的大小写只有一行代码,如果您需要编写如下所示的代码块,该怎么办:
private static int switchWithBlock(String day){int numOfDays = switch (day){case "Monday","Friday" -> 6;case "Tuesday" ->7;case "Wednesday" ->9;case "Thursday" ->8;default ->{int len = day.length();yield len;}};return numOfDays;
}
并且如果您使用类似“** switchWithBlock(“ bizzare”)**”,则默认情况下方法将返回7。 在这里,您必须注意yield,它表示产生值的语句。
switch语句(但不是switch表达式)可以是break语句的目标。 相反,switch表达式而不是switch语句可以成为yield语句的目标。
###局部变量的范围
在switch语句中,如果您在某种情况下声明了局部变量,其他情况也将可以访问该局部变量(局部变量的可见性也仅作为贯穿),请参见以下代码
switch (day){case MONDAY:int expense = 50;System.out.println("Monday expense is " + 50);break;case TUESDAY: {expense = 90;break;}
}
这里的变量“费用”也适用于TUESDAY情况,即使在MONDAY情况下也是如此。
如果您想停止这种行为,而在特定情况下声明为块的变量在上述示例中的另一个变量中不可用,则必须使用switch语句编写这样的代码
switch (day){case MONDAY: {int expense = 50;System.out.println("Monday expense is " + expense);break;}case TUESDAY: {int expense = 90;System.out.println("Tuesday expense is " +expense);break;}
}
此处声明变量“ expense”,仅在特定情况下使用。
现在,让我们看看局部变量如何与switch表达式一起使用,请参见以下代码段:
switch (day){case MONDAY ->{int expense = 50;System.out.println("Monday expense is "+expense);}case TUESDAY ->{int expense = 60;System.out.println("Monday expense is "+expense);}
}
因为switch表达式仅允许表达式,block和throw在上述情况下表示为限制局部变量范围的block。
Note:- Both switch statement and switch expression are valid options with JDK 14 and beyond.
from: https://dev.to//imagarg/switch-expression-jep-361-1onk
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
