Java 13中新的关键字“ yield”是什么意思?

zer*_*ewl 8 java yield switch-statement java-13

Java 13引入了yield用于switch表达式的关键字。

我该如何使用它?它与默认值returnbreak值有什么区别?

And*_*lko 10

问答环节

如何使用?

  1. 需要完整块时,带有箭头标签:

    int value = switch (greeting) {
        case "hi" -> {
            System.out.println("I am not just yielding!");
            yield 1;
        }
        case "hello" -> {
            System.out.println("Me too.");
            yield 2;
        }
        default -> {
            System.out.println("OK");
            yield -1;
        }
    };
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用传统积木:

    int value = switch (greeting) {
        case "hi":
            System.out.println("I am not just yielding!");
            yield 1;
        case "hello":
            System.out.println("Me too.");
            yield 2;
        default:
            System.out.println("OK");
            yield -1;
    };
    
    Run Code Online (Sandbox Code Playgroud)

默认收益有什么区别?

一条return语句将控制权返回给方法(第8.4节,第§15.12节)或构造函数(第8.8节和第15.9节的调用者,而一条yield语句则通过使一个封闭的switch表达式产生一个指定值来转移控制权。

突破值有什么区别?

break值为语句赞成的下降yield声明。

规格

JLS 13附带有JEP 354规范,规范总结了我们需要了解的有关新产品的所有信息。请注意,它尚未合并到语言规范中,因为它仍然是预览功能,因此不是该语言的永久组成部分。switch

一条yield语句通过使一个封闭的switch表达式产生一个指定值来转移控制权。

YieldStatement:
    yield Expression;
Run Code Online (Sandbox Code Playgroud)

一条yield语句试图将控制权转移到最内层的switch表达式;该表达式(称为yield target)随后立即正常完成,并且的值Expression成为switch表达式的值。

  • 如果yield语句没有屈服目标,则是编译时错误。

  • 如果yield目标包含包围yield语句的任何方法,构造函数,初始化程序或lambda表达式,则是编译时错误。

  • 这是一个编译时错误,如果Expression一个的yield声明是无效的(15.1)。

执行yield语句首先评估Expression。如果由于Expression某种原因突然完成了评估,则该yield语句由于该原因而突然完成。如果对值的评估Expression正常完成,则产生一个值V,然后该yield语句突然完成,原因是带有值的产量V


use*_*900 8

作为JEP 354(Java 13)的一部分,您可以在switch中产生值(可以选择将其分配给变量)

yield语句产生一个值,该值成为封闭开关表达式的值。

int j = switch (day) {
    case MONDAY  -> 0;
    case TUESDAY -> 1;
    default      -> {
        int k = day.toString().length();
        int result = f(k);
        yield result;
    }
};
Run Code Online (Sandbox Code Playgroud)

我认为您对Java 12上的JEP 325感到困惑,它使用break返回值:

我们扩展了break语句以接受一个参数,该参数成为封闭的switch表达式的值。

int j = switch (day) {
     case MONDAY  -> 0;
     case TUESDAY -> 1;
     default      -> {
         int k = day.toString().length();
         int result = f(k);
         break result;
Run Code Online (Sandbox Code Playgroud)

此外,您甚至可以使用lambda语法

boolean result = switch (ternaryBool) {
    case TRUE -> true;
    case FALSE -> false;
    case FILE_NOT_FOUND -> throw new UncheckedIOException(
        "This is ridiculous!",
        new FileNotFoundException());
    // as we'll see in "Exhaustiveness", `default` is not necessary
    default -> throw new IllegalArgumentException("Seriously?! ");
};
Run Code Online (Sandbox Code Playgroud)

使用switch表达式,整个switch块“获取一个值”,然后可以对其进行分配;您可以使用lambda样式的语法

虽然Java 12引入了13并完善了开关表达式,但它们是作为预览语言功能进行的。这意味着(a)在接下来的几个发行版中仍可以更改(如在12和13之间所做的那样),并且(b)需要在编译时和运行时使用新的命令行选项--enable-对其进行解锁。预习。然后请记住,这并不是转换的最终目标–这只是迈向完整模式匹配的一步。

  • @Druckles发生了更改,因为在我们与用户的研究中,人们发现`break`的重载令人困惑。 (5认同)
  • @Druckles似乎可以选择将* break *用于断开开关,将* yield *用于返回值,请参见https://metebalci.com/blog/what-is-new-in-java-13/#jep-354-还可使用break的switch-expressions-preview可以移至标签,请参阅https://docs.oracle.com/javase/specs/jls/se13/preview/switch-expressions.html#jep354-14.21 (2认同)
  • @BrianGoetz,这*令人困惑。不过,我喜欢[这里]提到的两种形式的“return”的类比(https://openjdk.java.net/jeps/325) (2认同)

Cod*_*ode 6

yield标记要从 switch 分支返回的值。它终止 switch 表达式,后面不需要有break。

来自文档

两个语句,break(带或不带标签)和yield,有助于轻松消除switch 语句和switch 表达式之间的歧义:switch 语句而不是switch 表达式可以作为break 语句的目标;并且 switch 表达式但不能是 switch 语句可以作为yield 语句的目标。

它还提供,NullPointerException安全,

String message = switch (errorCode) {
    case 404:
        yield "Not found!";
    case 500:
        yield "Internal server error!";
    // No default
};
Run Code Online (Sandbox Code Playgroud)

这将导致,

switch 表达式未涵盖所有可能的输入值