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

Why Switch requires statement but accepts expressions

我正在研究 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;
}

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

提前致谢。

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

Statements are roughly equivalent to sentences in natural languages. A statement forms a complete unit of execution. The following types of expressions can be made into a statement by terminating the expression with a semicolon (;).

  • Assignment expressions
  • Any use of ++ or --
  • Method invocations
  • Object creation expressions

Such statements are called expression statements. Here are some examples of expression statements:

// assignment statement
aValue = 8933.234;

// increment statement
aValue++;

// method invocation statement
System.out.println("Hello World!");

// object creation statement
Bicycle myBike = new Bicycle();

2 + 2true 是其中的 none,因为它们是表达式,因此在您的 switch 语句中出现编译错误。

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

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

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

换句话说,switch表达式的所有分支需要是相同类型的表达式,switch语句的分支需要是语句。方法调用 dog() 两者兼而有之,因此它可以在任一上下文中使用。

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

14.8. Expression Statements

Certain kinds of expressions may be used as statements by following them with semicolons.
ExpressionStatement:
StatementExpression ;
StatementExpression:
Assignment
PreIncrementExpression
PreDecrementExpression
PostIncrementExpression
PostDecrementExpression
MethodInvocation
ClassInstanceCreationExpression

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

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