Examining the "Boolean-Switch" in Java \_(ツ)_/

Examining the “Boolean-Switch” in Java ¯\(ツ)

探究 Java 中的“布尔 Switch” ¯\(ツ)

While reading through some AI-generated code today, I was caught off guard when I saw a switch statement inside of a boolean. What on earth has AI done now, I wondered. Here is the suspect:

今天在阅读一些 AI 生成的代码时,我惊讶地发现了一个嵌套在布尔逻辑中的 switch 语句。我不禁感叹,AI 到底搞了什么名堂?以下是这段“嫌疑代码”:

public boolean canChangeTo(OrderStatus newStatus) {
    switch (this) {
        case PLACED: return newStatus == PROCESSING || newStatus == CANCELLED;
        case PROCESSING: return newStatus == SHIPPED || newStatus == CANCELLED;
        case SHIPPED: return newStatus == DELIVERED;
        default: return false;
    }
}

Shortly after marveling at “ooo, this is a thing?” I started to question it. Why does this feel different? Basically in every other case besides enum, this is bad. Enum, to my knowledge, is the only case where this is acceptable. Why? Because in a flow where there can be one and only one direction, like order processing, this checks out. Each one will hit in the order it is intended to hit. Each case will be found true at the right time in the process, and will update the status accordingly.

在感叹“噢,原来还能这样?”之后,我开始反思。为什么这种写法感觉很特别?基本上,除了枚举(enum)之外,在其他任何情况下这样写都是糟糕的。据我所知,枚举是唯一适用此场景的情况。为什么?因为在订单处理这种流程中,状态流转通常是单向的,这种写法逻辑上是成立的。每个状态都会按预期的顺序触发,在流程的正确节点被判定为真,并相应地更新状态。

We can define our fixed, or set values (enums, short for enumeration) to use later in our switch. That might look like:

我们可以定义固定的值(枚举,即 enumeration 的缩写)以便稍后在 switch 中使用。代码如下:

public enum OrderStatus {
    PLACED("Placed"),
    PROCESSING("Processing"),
    SHIPPED("Shipped"),
    DELIVERED("Delivered"),
    CANCELLED("Cancelled");
}

We use enums when we have a distinct list of choices that do not change. This could also work for days of the week or the current states of your most recent job applications. Because we are using enum, we avoid typos. Also, using your choices as enum values makes them classes in Java - a whole ‘nother level of excitement.

当我们有一组不会改变的固定选项时,就会使用枚举。这同样适用于一周中的某一天,或者你最近求职申请的当前状态。因为使用了枚举,我们避免了拼写错误。此外,将选项作为枚举值使用,意味着它们在 Java 中是类(class)——这又带来了全新的可能性。

But back to my boolean-switch… Upon doing further digging I discovered that what Claude had spat out (no hate on Claude, I love Claude!) was actually not optimized. There is a better way to write the boolean-switch. Since Java 14, we can use arrows to slim down our writing.

回到我的“布尔 switch”话题……经过深入挖掘,我发现 Claude 生成的代码(并非针对 Claude,我还是很喜欢它的!)其实并未优化。有一种更好的方式来编写这种布尔 switch。从 Java 14 开始,我们可以使用箭头语法(arrow syntax)来精简代码:

public boolean canChangeTo(OrderStatus newStatus) {
    return switch (this) {
        case PLACED -> newStatus == PROCESSING || newStatus == CANCELLED;
        case PROCESSING -> newStatus == SHIPPED || newStatus == CANCELLED;
        case SHIPPED -> newStatus == DELIVERED;
        default -> false;
    };
}

…slimmer and concise! My brain likes this better. A peculiar boolean-switch has made me realize that using enums is incredibly more powerful and efficient than writing a string in an if-else statement. By using the this keyword on the switch statement itself, it evaluates the enum value and not the boolean value. If you want to “switch” on the boolean, then just use an if-else statement, because there is only two values anyways… I used to lean into if-else statements, but the switch is starting to grow on me.

……更精简、更简洁!我的大脑更喜欢这种写法。这个奇特的布尔 switch 让我意识到,使用枚举比在 if-else 语句中写字符串要强大且高效得多。通过在 switch 语句本身使用 this 关键字,它评估的是枚举值而非布尔值。如果你想对布尔值进行“switch”,直接用 if-else 就行了,毕竟布尔值只有两种情况……我过去倾向于使用 if-else,但现在我开始喜欢上 switch 了。