【问题标题】:Return outside of enclosing switch expression在封闭的 switch 表达式之外返回
【发布时间】:2019-11-10 09:53:43
【问题描述】:

我在 Java 12 中使用 switch 表达式¹将字符串转换为 HTTP method:

static Optional<RequestMethod> parseRequestMethod(String methodStr) {
    return Optional.ofNullable(
          switch (methodStr.strip().toUpperCase(Locale.ROOT)) {
              case "GET" -> RequestMethod.GET;
              case "PUT" -> RequestMethod.PUT;
              case "POST" -> RequestMethod.POST;
              case "HEAD" -> RequestMethod.HEAD;

              default -> {
                  log.warn("Unsupported request method: '{}'", methodStr);
                  return null;
              }
          });
}

我想警告默认分支中不支持的方法并返回 null(然后将其包装在 Optional 中)。

但是上面的代码会导致编译错误:

在封闭的 switch 表达式之外返回

如何编译?


为了完整起见,这里是 RequestMethod 枚举的定义:

enum RequestMethod {GET, PUT, POST, HEAD}

¹ switch expressions 在 Java 12 中作为预览功能引入。

【问题讨论】:

  • 为什么不使用RequestMethod.valueOf(methodStr.strip().toUpperCase(Locale.ROOT))
  • @VGR:因为这会引发 IllegalArgumentException。但问题中的代码只是显示编译器错误“返回封闭开关表达式之外”如何发生的示例。
  • 表达式(包括 switch 表达式)必须要么产生一个值,要么抛出。你不能 breakcontinuereturn 到其他上下文,除了正常完成(使用值;break value 在 12,更改为 yield value 在 13)或投掷。

标签: java switch-statement java-12 java-13


【解决方案1】:

在 Java 13 中使用 yield

在 Java 13 中,switch 表达式使用新的受限标识符¹ yield 从块中返回值:

return Optional.ofNullable(
        switch (methodStr.strip().toUpperCase(Locale.ROOT)) {
            case "GET" -> RequestMethod.GET;
            // ... rest omitted

            default -> {
                log.warn("Unsupported request method: '{}'", methodStr);
                // yield instead of return
                yield null;
            }
        });

在 Java 12 中使用 break

在 Java 12 中,switch 表达式使用break 从块中返回值:

return Optional.ofNullable(
        switch (methodStr.strip().toUpperCase(Locale.ROOT)) {
            case "GET" -> RequestMethod.GET;
            // ... rest omitted

            default -> {
                log.warn("Unsupported request method: '{}'", methodStr);
                // break instead of return
                break null;
            }
        });

¹yieldnot a keyword,正如用户 skomisa 有用地指出的那样。

【讨论】:

  • 感谢您教导我:是时候密切关注这些新的 Java 版本了。它们产生了意想不到的内容,这让我大吃一惊。
  • 学究式,关于 "...新关键字 yield...",Java 13 的 JLS 提议,其中包含 JEP 354 的更改(“切换表达式”)明确指出 yield 不是关键字。来自section 3.9 Keywords“受限标识符 var 和 yield 不是关键字……yield 在 yield 语句中具有特殊含义……”。还值得注意的是,相比之下,break 是一个关键字。在这个阶段向 Java 中添加新的关键字(尤其是 yield)可能会有很大的问题......
  • ...所以大概yield应该被描述为一个“受限标识符”而不是一个“关键字”。您可以轻松验证 yield 不是关键字,因为 int yield = 0; 在 Eclipse 2019-09 的 Java 13 上编译得很好。相反,int break = 0; 给出错误 Syntax error on token "break", invalid VariableDeclarator
  • Java (JEP/JLS) 文档中的另一个不一致之处:虽然break 用于从开关表达式中产生一个值,但corresponding JEP 的文档说,开关表达式可以完整的abruptly,这意味着 - return 也必须在这里工作..
猜你喜欢
  • 2021-05-18
  • 2015-06-06
  • 2019-08-01
  • 2020-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-19
  • 2017-12-09
相关资源
最近更新 更多