Return outside of enclosing switch expression
Asked Answered
S

1

20

I'm using a switch expression¹ in Java 12 to convert a string to a 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;
              }
          });
}

I'd like to warn about the unsupported method in the default branch and return null (which is then wrapped in an Optional).

But the code above causes a compiler error:

Return outside of enclosing switch expression

How do I get this to compile?


For completeness, here's the definition of the RequestMethod enum:

enum RequestMethod {GET, PUT, POST, HEAD}

¹ switch expressions were introduced in Java 12 as a preview feature.

Skillful answered 28/6, 2019 at 12:24 Comment(3)
Why not use RequestMethod.valueOf(methodStr.strip().toUpperCase(Locale.ROOT))?Indoeuropean
@VGR: Because that can throw an IllegalArgumentException. But the code in the question is only an example showing how the compiler error "Return outside of enclosing switch expression" can occur.Skillful
Expressions (including switch expressions) must either yield a value, or throw. You cannot break, continue, or return to other contexts, other than completing normally (with a value; break value in 12, changed to yield value in 13) or throwing.Dunnite
S
41

use yield in Java 13

In Java 13, switch expressions use the new restricted identifier¹ yield to return a value from a block:

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

use break in Java 12

In Java 12, switch expressions use break to return a value from a block:

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

¹ yield is not a keyword, as helpfully pointed out by user skomisa.

Skillful answered 28/6, 2019 at 12:24 Comment(5)
Thank for teaching me: it is time to closely closely observe these new Java releases. They yield unexpected content, which breaks out of my mind.Phosphorism
Being pedantic, regarding "...the new keyword yield...", the proposed JLS for Java 13 which incorporates changes for JEP 354 ("Switch Expressions") explicitly states that yield is not a keyword. From section 3.9 Keywords: "The restricted identifiers var and yield are not keywords....yield has special meaning in a yield statement...". It's also worth noting that in contrast, break is a keyword. Adding new keywords to Java at this stage (and yield in particular) might be highly problematic...Incorporation
... So presumably yield should be described as a "restricted identifier" rather than a "keyword". You can easily verify that yield is not a keyword because int yield = 0; compiles just fine on Java 13 in Eclipse 2019-09. In contrast, int break = 0; gives the error Syntax error on token "break", invalid VariableDeclaratorIncorporation
Yet another inconsistency in Java (JEP/JLS) documentation: while it's true, that break is used to yield a value from switch expressions, corresponding JEP's document says, that switch expressions can complete abruptly, which means - return must also be working here..Krone
@GiorgiTsiklauri this line might explain that inconsistency: The only reason an expression can complete abruptly is that an exception is thrown, because of either a throw with a given value (§14.18) or a run-time exception or error (§11 (Exceptions), §15.6).Discovery

© 2022 - 2024 — McMap. All rights reserved.