为啥 Switch 需要语句但接受表达式

Posted

技术标签:

【中文标题】为啥 Switch 需要语句但接受表达式【英文标题】:Why Switch requires statement but accepts expressions为什么 Switch 需要语句但接受表达式 【发布时间】:2021-12-26 07:02:26 【问题描述】:

我正在研究 switch 表达式,我想我发现了一个奇怪的行为:

public static boolean isTimeToParty(Day day) 
    switch (day) 
        case MONDAY -> dog(); //expression allowed
        case TUESDAY -> 2 + 2; //error: not a statement
        case WEDNESDAY -> true; //error: not a statement
        default -> System.out.println("");
    
    return false;


public static int dog() 
    return 2;

为什么我可以键入值dog() 这是一个表达式,但不允许使用其他类型的表达式? Intellij 提示我 "not a statement" 错误。

提前致谢。

【问题讨论】:

【参考方案1】:

根据语言规范,方法调用表达式也可以用作语句:

14.8. Expression Statements

某些类型的表达式可以用作语句,如下所示 他们用分号。 表达式语句: 语句表达式; StatementExpression: 赋值 PreIncrementExpression PreDecrementExpression PostIncrementExpression PostDecrementExpression MethodInvocation ClassInstanceCreationExpression

倒数第二行表示可以将方法调用表达式用作语句,这就是接受dog()的原因。返回值被简单地丢弃。 2 + 2 不能用作语句。

【讨论】:

【参考方案2】:

IntelliJ 识别出您正在尝试使用 switch 语句而不是 switch 表达式。如果您将代码更改为:

    int val = switch (day) 
        case MONDAY -> dog();
        case TUESDAY -> 2 + 2;
        case WEDNESDAY -> true;
        default -> System.out.println("");
    

您会发现错误现在与 print 语句和 true 值有关,因为它们无法转换为 int。这是因为 Intellij 现在将您的代码识别为 switch 表达式。

换句话说,switch 表达式的所有分支都必须是相同类型的表达式,switch 语句的分支必须是语句。方法调用dog() 是两者,因此它可以在任一上下文中工作。

【讨论】:

【参考方案3】:

问题是2 + 2true 不是Java 语句。在reference documentation 中我们可以看到以下内容:

语句大致相当于自然语言中的句子。一种 语句形成一个完整的执行单元。以下类型 表达式可以通过终止表达式变成语句 用分号 (;)。

赋值表达式 任何使用 ++ 或 -- 方法调用 对象创建表达式

这样的语句称为表达式语句。这里有一些 表达式语句示例:

// 赋值语句 aValue = 8933.234;

// 递增语句 一个值++;

// 方法调用语句 System.out.println("Hello World!");

//对象创建语句 自行车 myBike = new Bicycle();

2 + 2true 不是这些,因为它们是表达式,因此您的 switch 语句中会出现编译错误。

【讨论】:

switch 表达式中允许使用 -> 语法, 我不是说不是。我只是说 2 + 2true 不是语句,因此不允许在 switch 语句中。【参考方案4】:

开关在语句上下文中。一个语句也可能是一个方法调用,丢弃它的结果。还存在switch表达式,要求颠倒。

【讨论】:

以上是关于为啥 Switch 需要语句但接受表达式的主要内容,如果未能解决你的问题,请参考以下文章

switch结构case语句后的多个语句必须放在花括号中。 这句话对吗?为啥?

Switch基本知识

java中switch case怎么表示范围

switch注意事项

C#探索之路:表现力不够但简洁的switch 表达式

switch语句里不需要必须有break吗