c语言中switch表达式_看看Java 14中的新switch表达式

c语言中switch表达式

Java 14 is going to be released on March 17, 2020. The new version of Java contains an interesting update to the Java language: new switch expressions. Let’s see how the new switch expressions can be used, what kind of advantages they offer, and what can potentially go wrong. In the end, we’ll tackle a tricky question about switch expressions.

Java 14将于2020年3月17日发布。Java的新版本包含对Java语言的有趣更新:新的switch表达式。 让我们看看如何使用新的switch表达式,它们提供什么样的优势以及潜在的错误。 最后,我们将解决一个关于switch表达式的棘手问题。

经典的“转换”声明 (The Classic ‘Switch’ Statement)

The current design of the switch statement in Java follows languages such as C and C++. It works only as a statement and supports fall-through semantics by default. Here’s an example of the classic switch statement with an enum:

Java中switch语句的当前设计遵循诸如C和C ++之类的语言。 它仅用作语句,并且默认情况下支持穿透语义。 这是带有枚举的经典switch语句的示例:

public class ClassicSwitchStatement {


    enum Person {
        Mozart, Picasso, Goethe, Dostoevsky, Prokofiev, Dali
    }


    public static void main(String[] args) {
        print(Person.Mozart);
        print(Person.Dali);
        print(Person.Dostoevsky);
    }


    static void print(Person person) {
        switch (person) {
            case Dali:
            case Picasso:
                System.out.printf("%s was a painter%n", person);
                break;
            case Mozart:
            case Prokofiev:
                System.out.printf("%s was a composer%n", person);
                break;
            case Goethe:
            case Dostoevsky:
                System.out.printf("%s was a writer%n", person);
                break;
            default:
                throw new IllegalArgumentException(
                        String.format("Unknown person: %s", person));
        }
    }
}

You might have noticed many case and break statements in the example above. Those statements introduce some visual noise and make the code unnecessarily verbose. This visual noise may then mask mistakes such a missing break statement, which would mean accidental fall through.

在上面的示例中,您可能已经注意到很多case和break语句。 这些语句引入了一些视觉干扰,并使代码不必要地冗长。 然后,这种视觉噪音可能掩盖了诸如丢失中断声明之类的错误,这将意味着意外掉线。

新的“ Switch”表达 (The New ‘Switch’ Expressions)

Java 14 extends switch so it can be used as either a statement or an expression. In particular, the new Java introduces the following:

Java 14扩展了switch因此它可以用作语句或表达式。 特别是,新的Java引入了以下内容:

  • A new form of the switch label case ... ->, where only the code to the right of the label is going to be executed if the label is matched. The code to the right of a case ... -> label may be an expression, a block, or a throw statement.

    switch标签case ... ->一种新形式case ... -> ,如果匹配标签,则只执行标签右边的代码。 case ... ->标签右侧的代码可以是表达式,块或throw语句。

  • A new yield statement to yield a value that becomes the value of the enclosing switch expression

    一个新的yield语句,用于产生一个值,该值成为封闭switch表达式的值

  • Multiple constants per case that are separated by commas

    每个个案的多个常数,以逗号分隔

With the new Java 14, it’s possible to use both traditional case ... : labels and the new case ... -> labels. It’s important the traditional labels still support fall through by default, but the new ones don't need to.

使用新的Java 14,可以同时使用传统case ... :标签和新case ... ->标签。 重要的是,默认情况下,传统标签仍然支持掉线,但新标签则不需要。

Let’s see how the example above can be rewritten with the new switch expressions:

让我们看看如何使用新的switch表达式重写上面的示例:

public class WhoIsWho {


    enum Person {
        Mozart, Picasso, Goethe, Dostoevsky, Prokofiev, Dali
    }


    public static void main(String[] args) {
        print(Person.Mozart);
        print(Person.Dali);
        print(Person.Dostoevsky);
    }


    static void print(Person person) {
        String title = switch (person) {
            case Dali, Picasso      -> "painter";
            case Mozart, Prokofiev  -> "composer";
            case Goethe, Dostoevsky -> "writer";
        };
        System.out.printf("%s was a %s%n", person, title);
    }
}

This simple example can be compiled and run with just a single command (thanks to JEP 330, which has allowed the launching of single-file source-code programs since Java 11):

这个简单的示例仅需一个命令即可编译和运行(由于JEP 330,自Java 11开始就允许启动单文件源代码程序):

$ java WhoIsWho.java
Mozart was a composer
Dali was a painter
Dostoevsky was a writer

You can see several case statements have been merged, and the code doesn't use a break statement any more. As a result, the print() method became much shorter and looks nicer.

您会看到几个case语句已经合并,并且代码不再使用break语句。 结果, print()方法变得更短并且看起来更好。

The following example shows a multiline default block that uses the new yield statement to yield a value. Note that there are several new constants in the Person enum that aren’t covered by the case labels in the switch expression:

以下示例显示了一个多行default块,该块使用新的yield语句产生一个值。 请注意, Person枚举中有几个新常量未包含在switch表达式中的case标签中:

public class WhoIsWho {


    enum Person {
        Mozart, Picasso, Goethe, Dostoevsky, Prokofiev, Dali,


        Gaudi, Bach, Einstein
    }


    public static void main(String[] args) {
        print(Person.Mozart);
        print(Person.Dali);
        print(Person.Einstein);
    }


    static void print(Person person) {
        String title = switch (person) {
            case Dali, Picasso      -> "painter";
            case Mozart, Prokofiev  -> "composer";
            case Goethe, Dostoevsky -> "writer";
            default                 -> {
                System.out.printf("Oops! I don't know about %s%n", person);
                yield "...";
            }
        };
        System.out.printf("%s was a %s%n", person, title);
    }
}

Here’s what the program prints out:

程序输出如下:

$ java WhoIsWho.java 
Mozart was a composer
Dali was a painter
Oops! I don't know about Einstein
Einstein was a ...

The next example shows how factorial may be implemented with the new switch expressions:

下一个示例显示如何使用新的switch表达式实现factorial

static int factorial(int n) {
    return switch (n) {
        case 0, 1 -> 1;
        case 2    -> 2;
        default   -> factorial(n - 1) * n;
    };
}

重要细节 (Important Details)

There are several important things to know about the new switch expressions.

关于新的switch表达式,有几件重要的事情要知道。

The first thing to know is the cases of a switch expression must be exhaustive. In other words, for all possible values, there must be a matching switch label. Let’s just add a new element to the enum and see what’s going to happen:

首先要知道的是switch表达式的情况必须详尽。 换句话说,对于所有可能的值,必须有一个匹配的switch标签。 让我们向枚举添加一个新元素,看看会发生什么:

public class InvalidWhoIsWho {


    enum Person {
        Mozart, Picasso, Goethe, Dostoevsky, Prokofiev, Dali,


        // this element is not covered
        // by any case in the switch expression below
        // which results to compilation failure
        Gaudi
    }


    public static void main(String[] args) {
        print(Person.Mozart);
        print(Person.Dali);
        print(Person.Dostoevsky);
    }


    static void print(Person person) {
        String title = switch (person) {
            case Dali, Picasso      -> "painter";
            case Mozart, Prokofiev  -> "composer";
            case Goethe, Dostoevsky -> "writer";
        };
        System.out.printf("%s was a %s%n", person, title);
    }
}

Compilation will fail right away with the following error message:

编译将立即失败,并显示以下错误消息:

$ java InvalidWhoIsWho.java
InvalidWhoIsWho.java:19: error: the switch expression does not cover all possible input values
String title = switch (person) {
^
1 error
error: compilation failed

Adding a simple default case makes the Java compiler happy:

添加一个简单的default情况使Java编译器满意:

String title = switch (person) {
    case Dali, Picasso      -> "painter";
    case Mozart, Prokofiev  -> "composer";
    case Goethe, Dostoevsky -> "writer";
    default                 -> "...";                     
};

In general, unless an enum is used and the cases of a switch expression cover all constants, a default clause is required in the switch expression.

通常,除非使用一个枚举和的情况下, switch表达涵盖所有常量,一个default子句需要在switch的表达。

The second thing to remember is a switch expression must either complete normally with a value or by throwing an exception. Let’s take a look at the following code:

要记住的第二件事是, switch表达式必须正常完成一个值或抛出异常。 让我们看下面的代码:

public class InvalidSwitchExpressionWithoutDefault {


    public static void main(String[] args) {
        System.out.println(print(1));
    }


    static String print(int n) {
        return switch (n) {
            case 0 -> "zero";
            case 1 -> "one";
            case 2 -> "two";
        };
    }
}

If we try to compile this code, the Java compiler will immediately complain:

如果我们尝试编译此代码,则Java编译器将立即抱怨:

InvalidSwitchExpressionWithoutDefault.java:8: error: the switch expression does not cover all possible input values
return switch (n) {
^
1 error
error: compilation failed

Again, adding a default case makes it work:

同样,添加default大小写使其起作用:

static String print(int n) {
    return switch (n) {
        case 0  -> "zero";
        case 1  -> "one";
        case 2  -> "two";
        default -> "many";
    };
}

The third important thing to keep in mind is yield is now a restricted identifier. In particular, it means that classes named yield become illegal:

要记住的第三件事是, yield现在是一个受限制的标识符。 特别是,这意味着名为yield类变为非法:

$ cat YieldClassName.java 
class yield {}
$ javac YieldClassName.java
YieldClassName.java:1: error: 'yield' not allowed here
class yield {
^
as of release 13, 'yield' is a restricted type name and cannot be used for type declarations
1 error
error: compilation failed

However, it’s allowed to use yield as a variable or a method name:

但是,允许将yield用作变量或方法名称:

$ cat ValidUseOfYieldWord.java 
public class ValidUseOfYieldWord {
void yield() {
int yield = 0;
}
}
$ javac ValidUseOfYieldWord.java && echo ok || echo failed
ok

结论 (Conclusion)

Here’s what the authors say about the new switch expressions:

这是作者对新switch表达式的评价:

“These changes will simplify everyday coding.”

“这些更改将简化日常编码。”

Let’s see.

让我们来看看。

奖金 (Bonus)

What do you think is going to happen? Here are the options:

您认为会发生什么? 以下是选项:

  1. Compilation error.

    编译错误。
  2. Runtime error.

    运行时错误。
  3. Oops is printed out.

    Oops

  4. OopsOops is printed out

    OopsOops打印出来

  5. Forty-two is printed out.

    打印出Forty-two

public class StrangeYield {


    public static void main(String[] args) {
        go(0);
    }


    static void go(int n) {
        System.out.println(
            switch (n) {
                case 42 -> "Fotry-two";
                default -> {
                    yield("Oops");
                }
            }
        );
    }


    static String yield(String s) {
        return s + "Oops";
    }
}

翻译自: https://medium.com/better-programming/a-look-at-the-new-switch-expressions-in-java-14-ed209c802ba0

c语言中switch表达式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值