【问题标题】:What does the new keyword "yield" mean in Java 13?Java 13 中的新关键字“yield”是什么意思?
【发布时间】:2020-01-22 17:42:56
【问题描述】:

Java 13 为 switch 表达式引入了 yield 关键字。

如何使用它以及与默认的 returnbreak 值有什么区别?

【问题讨论】:

  • 它只用于从switch statement 内部指定返回值。它与 return 不同,因为它从语句中产生,而不是从方法中返回
  • @BoristheSpider Java 12 使用了break <value>return <value> 仅被考虑为 iirc,但从未成为发布版本的一部分。

标签: java switch-statement yield java-13


【解决方案1】:

问答

我该如何使用它?

  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;
        }
    };
    
  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;
    };
    

与默认退货有什么区别?

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

与中断值有什么区别?

break with value 语句被删除,取而代之的是 yield 语句。

规格

Specification for JEP 354 附加到 the JLS 13,它总结了我们需要了解的有关新 switch 的所有信息。请注意,它没有合并到语言规范中,因为它仍然是 a preview feature,因此还不是语言的永久部分。

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

YieldStatement:
    yield Expression;

yield 语句试图将控制权转移到最里面的封闭开关表达式;这个表达式被称为yield target,然后立即正常完成,Expression 的值变成了switch 表达式的值。

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

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

  • 如果 yield 语句的 Expression 为 void (15.1),则会出现编译时错误。

yield 语句的执行首先评估Expression。如果Expression 的评估由于某种原因突然完成,那么yield 语句会因为这个原因而突然完成。如果Expression 的评估正常完成,产生一个值V,那么yield 语句会突然完成,原因是一个带有值V 的yield。

【讨论】:

    【解决方案2】:

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

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

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

    我认为您的困惑在于 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;
    

    另外,你甚至可以使用lambda syntax

    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?! ?");
    };
    

    使用 switch 表达式,整个 switch 块“得到一个值”,然后可以赋值;你可以使用 lambda 风格的语法

    虽然 Java 12 引入并 13 改进了 switch 表达式,但它们是作为预览语言功能这样做的。这意味着(a)它仍然可以在接下来的几个版本中发生变化(就像它在 12 和 13 之间所做的那样)和(b)它需要在编译时和运行时使用新的命令行选项--enable-解锁预习。然后请记住,这不是 switch 的最后阶段——它只是通往完全模式匹配的一步。

    【讨论】:

    • 有谁知道为什么从 JDK 12 改变了这个? JEP 并没有提供太多关于为什么选择 yield 而不是 break
    • @Druckles 似乎可以选择将 break 用于中断开关和 yield 用于返回值,请参阅metebalci.com/blog/what-is-new-in-java-13/… 也使用 break 可以移动到标签见docs.oracle.com/javase/specs/jls/se13/preview/…
    • @Druckles 之所以更改,是因为在我们对用户的研究中,人们发现break 的超载令人困惑。
    • @BrianGoetz 它令人困惑。不过,我喜欢与return 提到的两种形式的类比here
    • return@ 在 Kotlin 中是比 new 关键字更好的解决方案...
    【解决方案3】:

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

    来自doc

    这两个语句,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
    };
    

    这将导致,

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

    【讨论】:

      【解决方案4】:

      在java 13中用yield替换break。这是java 13中定义的预览功能之一。在Java 12中,我们可以使用break从开关中返回一个值。但在 java 13 中,yield 用于 switch 表达式的返回值。

      In Java 13 break replace by yield,

      String number = switch (number) {
          case 1:
              yield "one";
          case 2:
              yield "two";
          default:
              yield "Zero";
      }
      

      Java 13 仍然支持箭头语法。

      String number = switch (number) {
          case 1 -> "one";
          case 2 -> "two";
          default -> "Zero";
      }
      

      【讨论】:

      • yield 不会取代break,它增加了不同的功能。
      • 请在示例末尾添加;,因为目前它无法编译:)
      猜你喜欢
      • 2011-07-11
      • 2011-02-14
      • 2010-10-29
      • 2011-10-28
      • 1970-01-01
      • 2014-12-19
      相关资源
      最近更新 更多