Yesterday morning, I reviewed the codes of two new colleagues by remote way. Most of the codes were beautifully written, rigorous and well annotated, which made me very satisfied. But when I saw the switch statement written by one of them, I couldn’t help Shouting: “Oh my god, Xiao Wang, your switch statement is too old-fashioned!”

Take a look at the code written by Xiao Wang, don’t scold me after reading it.

private static String createPlayer(PlayerTypes playerType) {    switch (playerType) {        case TENNIS:            return "Federer the Tennis player.";        case FOOTBALL:            return "Cristiano Ronaldo, soccer player.";        case BASKETBALL:            return "James the Basketball Player";        case UNKNOWN:            throw new IllegalArgumentException("Unknown");        default:            throw new IllegalArgumentException(                    "Type of athlete:" + playerType);    }}
Copy the code

After looking at the code above, are you going to say something like, “Well written, there are no problems!” Do you think I am making trouble out of nothing and blaming Xiao Wang wrongly? But here’s a line from The Great Gatsby:

When I was younger and less experienced, my father taught me something that I still remember. “Whenever you feel like criticizing any one,” he told me, “just remember that all the people in this world haven’t had the advantages that you’ve had.”

Haha, this one is not only for you, but also for me. It’s time to calm down and talk about the cliche of the switch statement above.

[Image upload failed…(image-632ba4-1583291507001)]

If the default statement is accidentally deleted, the compiler will say “no return statement”. To solve this problem, we can create a new player variable as the return result, like the following:

private static String createPlayer(PlayerTypes playerType) {    String player = null;    switch (playerType) {        case TENNIS:            player = "Federer the Tennis player.";            break;        case FOOTBALL:            player = "Cristiano Ronaldo, soccer player.";            break;        case BASKETBALL:            player = "James the Basketball Player";            break;        case UNKNOWN:            throw new IllegalArgumentException("Unknown");    }    returnplayer; }Copy the code

When the player variable is added, the case statement needs to add the break keyword; In addition, after the switch statement ends, return player. The compiler does not indicate any errors, indicating that the default statement can be omitted in this case.

Starting with JDK 12 (JDK 13 is used in this example), the switch statement has been updated to not only be used as a conditional judgment like a traditional switch statement, but also as a direct return result. To modify Xiao Wang’s code, as shown below:

private static String createPlayer(PlayerTypes playerType) {   return switch (playerType) {        case TENNIS -> "Federer the Tennis player.";        case FOOTBALL -> "Cristiano Ronaldo, soccer player.";        case BASKETBALL -> "James the Basketball Player";        case UNKNOWN ->  throw new IllegalArgumentException("Unknown"); }; }Copy the code

Enough fashion? Not only does the return keyword precede the switch keyword, but there is also a shadow of the Lambda expression in case, where the dash and arrow have replaced the colon, meaning that the code to the right of the arrow does not need to break.

Also, the default statement becomes optional. Try it yourself.

The new Switch statement is smart enough to validate conditions of enumerated types in addition to the three advantages described above. Add a new type PINGPANG to PlayerTypes:

public enum PlayerTypes {    TENNIS,    FOOTBALL,    BASKETBALL,    PINGPANG,    UNKNOWN}
Copy the code

The compiler issues the following warning:

This means that the case condition in the switch does not fully cover the possible values in the enumeration. Ok, so add the PINGPANG condition. Take a look at the complete code:

public class OldSwitchDemo {    public enum PlayerTypes {        TENNIS,        FOOTBALL,        BASKETBALL,        PINGPANG,        UNKNOWN    }    public static void main(String[] args) {        System.out.println(createPlayer(PlayerTypes.BASKETBALL));    }    private static String createPlayer(PlayerTypes playerType) {        return switch (playerType) {            case TENNIS -> "Federer the Tennis player.";            case FOOTBALL -> "Cristiano Ronaldo, soccer player.";            case BASKETBALL -> "James the Basketball Player";            case PINGPANG -> "Ma Long, table Tennis Player.";            case UNKNOWN -> throw new IllegalArgumentException("Unknown");        };    }}
Copy the code

The switch statement becomes a powerful switch expression. What if a player can play both basketball and table tennis?

private static String createPlayer(PlayerTypes playerType) {    return switch (playerType) {        case TENNIS -> "Federer the Tennis player.";        case FOOTBALL -> "Cristiano Ronaldo, soccer player.";        case BASKETBALL,PINGPANG -> "Awesome athlete Silent King two.";        case UNKNOWN -> throw new IllegalArgumentException("Unknown"); }; }Copy the code

As in the above code, use the English comma “, “to separate the condition. 666 ah!

Defy spirit? Even better, switch expressions can have blocks of code enclosed in {} to the right, just as Lambda expressions do.

private static String createPlayer(PlayerTypes playerType) {    return switch (playerType) {        case TENNIS -> {            System.out.println("Tennis");            yield "Federer the Tennis player.";        }        case FOOTBALL -> {            System.out.println("Football");            yield "Cristiano Ronaldo, soccer player.";        }        case BASKETBALL -> {            System.out.println("Basketball");            yield "James the Basketball Player";        }        case PINGPANG -> {            System.out.println("Table tennis");            yield "Ma Long, table Tennis Player.";        }        case UNKNOWN -> throw new IllegalArgumentException("Unknown"); }; }Copy the code

The observant student will find a new keyword, yield, which is different from the traditional return or break keyword.

First, the official explanation:

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

This means that the yield statement transfers control by making a closed switch expression yield a specified value. To learn more about the yield keyword, we can decompile the bytecode:

private static String createPlayer(NewSwitchDemo3.PlayerTypes playerType) {    String var10000;    switch(playerType) {        case TENNIS:            System.out.println("Tennis");            var10000 = "Federer the Tennis player.";            break;        case FOOTBALL:            System.out.println("Football");            var10000 = "Cristiano Ronaldo, soccer player.";            break;        case BASKETBALL:            System.out.println("Basketball");            var10000 = "James the Basketball Player";            break;        case PINGPANG:            System.out.println("Table tennis");            var10000 = "Ma Long, table Tennis Player.";            break;        case UNKNOWN:            throw new IllegalArgumentException("Unknown");        default:            throw new IncompatibleClassChangeError();    }    returnvar10000; }Copy the code

The compiler automatically escapes the yield keyword during bytecode generation and converts it into a traditional break statement. Does that make sense?

But then again, the code that looks like fashion is just handing over some of the work to the compiler to show off skills, and it can also be incompatible with older versions and unfriendly to teammates.

“Sorry, I apologize for being so aggressive yesterday morning…” I sent a message to Xiao Wang.

Well, my dear readers, that’s all for this article, hoping to please you