81

Java 13 introduced the yield keyword for switch expressions.

How can I use it and what's the difference to a default return or break value?

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
zerocewl
  • 11,401
  • 6
  • 27
  • 53
  • 5
    It is only ever used to specify a return value from inside a [`switch` statement](https://www.vojtechruzicka.com/java-enhanced-switch/). It is different to a `return` as it _yields_ from a statement as opposed to _returns_ from a method. – Boris the Spider Sep 22 '19 at 12:25
  • 4
    @BoristheSpider Java 12 used `break `, the `return ` was iirc only considered, but never part of a released version. – Mark Rotteveel Sep 22 '19 at 12:28
  • It is worth noting that `yield` is not a keyword. `Thread` has a `yield()` method that is there to stay, and you can name any of your vairables, fields, methods or labels `yield` long as your namespace allows it. – Ahmad Shahwan Oct 18 '22 at 19:36

4 Answers4

82

Q&A

How can I use it?

  1. With arrow labels when a full block is needed:

    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. With traditional blocks:

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

What's the difference to a default return?

A return statement returns control to the invoker of a method (§8.4, §15.12) or constructor (§8.8, §15.9) while a yield statement transfers control by causing an enclosing switch expression to produce a specified value.

What's the difference to a break value?

The break with value statement is dropped in favour of a yield statement.

Specification

There is Specification for JEP 354 attached to the JLS 13 which sums up everything we need to know about the new switch. Note that it wasn't merged into the language specification because it's still a preview feature and, thus, not yet a permanent part of the language.

A yield statement transfers control by causing an enclosing switch expression to produce a specified value.

YieldStatement:
    yield Expression;

A yield statement attempts to transfer control to the innermost enclosing switch expression; this expression, which is called the yield target, then immediately completes normally and the value of the Expression becomes the value of the switch expression.

  • It is a compile-time error if a yield statement has no yield target.

  • It is a compile-time error if the yield target contains any method, constructor, initializer, or lambda expression that encloses the yield statement.

  • It is a compile-time error if the Expression of a yield statement is void (15.1).

Execution of a yield statement first evaluates the Expression. If the evaluation of the Expression completes abruptly for some reason, then the yield statement completes abruptly for that reason. If evaluation of the Expression completes normally, producing a value V, then the yield statement completes abruptly, the reason being a yield with value V.

Naman
  • 27,789
  • 26
  • 218
  • 353
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
18

As part of JEP 354 (Java 13), you can yield value in switch (optionally assign it to variable)

yield statement to yield a value, which becomes the value of the enclosing switch expression.

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

I think your confusion is with JEP 325 on Java 12 that use break to return value:

we have extended the break statement to take an argument, which becomes the value of the enclosing switch expression.

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

In addition, you can even use 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?! ");
};

With switch expressions, the entire switch block "gets a value" that can then be assigned; you can use a lambda-style syntax

While Java 12 introduces and 13 refines switch expressions, they do so as a preview language feature. That means (a) it can still change over the next few releases (as it did between 12 and 13) and (b) it needs to be unlocked, at compile time and run time, with the new command line option --enable-preview. Then keep in mind that this isn’t the endgame for switch – it’s just a step on the way to full pattern matching.

Ori Marko
  • 56,308
  • 23
  • 131
  • 233
  • Anyone know why this was changed from JDK 12? The JEP doesn't give much insight into why `yield` was chosen over `break`. – Druckles Sep 22 '19 at 12:56
  • 3
    @Druckles it seems a choice to separate *break* for breaking switch and *yield* for returning value, see https://metebalci.com/blog/what-is-new-in-java-13/#jep-354-switch-expressions-preview also using break can move to label see https://docs.oracle.com/javase/specs/jls/se13/preview/switch-expressions.html#jep354-14.21 – Ori Marko Sep 22 '19 at 13:06
  • 8
    @Druckles It was changed because, in our research with users, people found the overloading of `break` confusing. – Brian Goetz Sep 22 '19 at 16:49
  • 1
    @BrianGoetz it *is* confusing. Though, I liked the analogy with the two forms of `return` mentioned [here](https://openjdk.java.net/jeps/325) – Andrew Tobilko Sep 22 '19 at 21:11
  • return@ in Kotlin is much better solution, than new keyword... – Andrew Sneck May 09 '21 at 07:43
5

yield marks value to be returned from a switch branch. It terminates the switch expression, you don't need to have break after it.

From doc

The two statements, break (with or without a label) and yield, facilitate easy disambiguation between switch statements and switch expressions: a switch statement but not a switch expression can be the target of a break statement; and a switch expression but not a switch statement can be the target of a yield statement.

It also provides, NullPointerException Safety,

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

This will result in,

the switch expression does not cover all possible input values

Vikas
  • 6,868
  • 4
  • 27
  • 41
1

break replace with yield in java 13. This is one of the preview feature defined in java 13.in Java 12, we can use break to return a value from a switch. But in java 13 yield use for the return value from switch expression.

In Java 13 break replace by yield,

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

Arrow syntax is still supported in Java 13.

String number = switch (number) {
    case 1 -> "one";
    case 2 -> "two";
    default -> "Zero";
}
Walery Strauch
  • 6,792
  • 8
  • 50
  • 57
ricky
  • 325
  • 2
  • 4