对于Java程序员来说,switch语句应该是非常熟悉的了,它是Java中结构控制的一种。相信大家使用的都比较多了。
但其实在Java 12,13以及最终的17中,Java都引进与优化了与switch语句有关联的一个新特性,那就是switch表达式
这篇文章是Java 8之后的那些新特性系列的第七篇。本系列的其它文章为:
要注意区分下,switch statement(switch语句)与switch expressions(switch表达式)两个词的不同。switch语句是大家熟悉的旧的switch用法,而 switch表达式则是我们今天要说的。
其实,从这两者之间的名字来看,就能猜到两者肯定有很大的相似性,也一定会有不同。
所以,要说switch表达式,我们一定得从switch语句说起。
public class SwitchTest {
@Test
void testSwitchStatement(){
var trafficLight = randomTrafficLight();
String lightString;
switch (trafficLight){
case LIGHT_RED: {
lightString = "红灯";
break;
}
case LIGHT_GREEN:{
lightString = "绿灯";
break;
}
case LIGHT_YELLOW: {
lightString = "黄灯";
break;
}
default: throw new IllegalArgumentException("不支持的信号灯");
}
Assertions.assertNotNull(lightString);
}
}
上述代码应该是大家都非常熟悉的switch语句的代码。在讨论过往的switch语句时,无论大家看哪个教程,都一定会提醒大家一件事:
不要忘记break语句
否则switch语句的执行过程会出乎你的意料之外。
当然,随着Java的发展,switch语句出现了一些问题,有待改进。主要包括:
因此,这也是switch表达式出现的原因所在。switch表达式其实你可以认为它就是switch语句的改进版。它主要解决了switch语句在上述三个方面的问题。
好吧,我们用switch表达式来重写上面这个代码,你看到的效果将是这样
public class SwitchTest {
@Test
void testSwitchExpression(){
var trafficLight = randomTrafficLight();
var lightString = switch (trafficLight) {
case LIGHT_YELLOW -> {
yield "黄灯";
}
case LIGHT_GREEN -> {
yield "红灯";
}
case LIGHT_RED -> {
yield "红灯";
}
};
Assertions.assertNotNull(lightString);
}
}
这是使用switch表达式来改写后的代码(这个可以再简化,但为了足够说明yield的作用,先这样)
通过上面这个改写,你可以很明显感知到,switch表达式可以做到:
而在switch表达式中,返回值是通过yield字段来处理的。并且,如果你只有一行返回值的情况下,可以省略掉block括号以及yield字段。
public class SwitchTest {
@Test
void testSwitchExpression(){
var trafficLight = randomTrafficLight();
var lightString = switch (trafficLight) {
case LIGHT_YELLOW -> "黄灯";
case LIGHT_GREEN -> "绿灯";
case LIGHT_RED -> "红灯";
};
Assertions.assertNotNull(lightString);
}
}
语法规则
注意,switch表达式的标准语法是
case label_1, label_2, ..., label_n -> expression;|throw-statement;|block
switch表达式用的是 ->(箭头号),而在switch语句中,用的是: (冒号)
switch表达式必须穷尽一切可能
与switch语句不同,switch语句并不需要穷尽一切值,而switch表达式则一定要穷尽一切可能值,如果你不想穷尽所有值,可以使用default.
public class SwitchTest {
@Test
void testSwitchStatement(){
var trafficLight = randomTrafficLight();
String lightString = null;
//switch语句可以不列出所有值,也可以没有default
switch (trafficLight){
case LIGHT_RED: {
lightString = "红灯";
break;
}
case LIGHT_GREEN:{
lightString = "绿灯";
break;
}
}
Assertions.assertNotNull(lightString);
}
}
但在switch表达式中,这是不允许的
public class SwitchTest {
@Test
void testSwitchExpression(){
var trafficLight = randomTrafficLight();
//这是不允许的,LIGHT_RED没有列上
var lightString = switch (trafficLight) {
case LIGHT_YELLOW -> "黄灯";
case LIGHT_GREEN -> "绿灯";
};
Assertions.assertNotNull(lightString);
}
}
上述代码会抛出编译错误:'switch' expression does not cover all possible input values
你可以加上case LIGHT_RED -> "红灯";
或者使用default
,这两种方式都可以。
上述只讲了switch表达式的两点,一个是它是表达式,二它不需要break,而switch表达式还可以搭配patten matching一同使用,做到模式自动匹配
这一点,我在下次再来说,聊一聊Pattern Matching这个新特性。
好了,这就是关于switch表达式的新特性,有了它,你可以忘掉过去那个会经常出错的switch语句了。
我是御剑,一个致力于实践与传播编码之道的全栈式程序员。
访问微言码道
(https://taoofcoding.tech)以阅读更多我写的文章;
访问myddd
(https://myddd.org)以了解我在维护的全栈式领域驱动开源框架。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有