{"id":"switch-and-text-switch-statements","slug":"switch-statements","title":"The switch statement","text":"This module is an extra: the MOOC doesn't cover it. It shows three pieces of Java that the course never needed, but that you'll meet in a lot of Java code written today: `switch`, which picks one of several branches by a value; `var`, which lets the compiler work out a local variable's type; and text blocks with `String.format`, for text of several lines and for lining up columns. None of them lets a program do something it couldn't do before. They make some code shorter, and often easier to read.\n\n### One value, many branches\n\nA snack machine has numbered buttons. With the tools of the course, a program that names the snack behind a button is a chain of `if` and `else if`:\n\n```java\nint button = 3;\nif (button == 1) {\n    System.out.println(\"Chips\");\n} else if (button == 2) {\n    System.out.println(\"Chocolate bar\");\n} else if (button == 3) {\n    System.out.println(\"Apple\");\n} else {\n    System.out.println(\"No such button\");\n}\n```\n\n```output\nApple\n```\n\nEvery condition compares the same variable with a different value. The `switch` statement says exactly that:\n\n```java\nint button = 3;\nswitch (button) {\n    case 1:\n        System.out.println(\"Chips\");\n        break;\n    case 2:\n        System.out.println(\"Chocolate bar\");\n        break;\n    case 3:\n        System.out.println(\"Apple\");\n        break;\n    default:\n        System.out.println(\"No such button\");\n}\n```\n\n```output\nApple\n```\n\n- `switch (button)` works out the value in the parentheses once. Then the program jumps to the `case` label with the same value, here `case 3:`, and runs the statements after it.\n- `break` ends the switch: the program goes on after its closing brace.\n- `default:` is where the program jumps when no label matches. It's optional: without it, a value that matches no label does nothing.\n- A label is a constant: a literal such as `3`, `'x'` or `\"tea\"`, or a `final` variable given a literal. Two labels of one switch can't have the same value; javac stops with \"duplicate case label\".\n- A switch on constants works on an `int` (and on the smaller whole-number types and `char`), on a String (since Java 7, step 3) and on an enum (step 3). It doesn't work on a `double`, a `long` or a `boolean`: `switch (price)` with a double price gives javac's error \"selector type double is not allowed\".\n\n### Falling through\n\nHere's what happens when a `break` is missing:\n\n```java\nint button = 1;\nswitch (button) {\n    case 1:\n        System.out.println(\"Chips\");\n    case 2:\n        System.out.println(\"Chocolate bar\");\n        break;\n    case 3:\n        System.out.println(\"Apple\");\n        break;\n}\n```\n\n```output\nChips\nChocolate bar\n```\n\nA `case` label only marks where the program starts. Once it's running the statements of a case, it keeps going, past the next label and into the next case's statements, until a `break` (or the end of the switch). This is called **falling through**. A forgotten `break` is the classic switch bug: javac says nothing, and the program does too much. The arrow labels of step 2 don't fall through, which is one reason they're preferred today.\n\n### Several values, one branch\n\nFalling through has one honest use: several labels in a row share the statements after the last of them. Buttons 4 and 5 are both water, still and sparkling:\n\n```java\nint button = 5;\nswitch (button) {\n    case 1:\n        System.out.println(\"Chips\");\n        break;\n    case 4:\n    case 5:\n        System.out.println(\"Water\");\n        break;\n    default:\n        System.out.println(\"Something else\");\n}\n```\n\n```output\nWater\n```\n\n`case 4:` has no statements of its own, so it falls straight through to `case 5:`. Since Java 14, the same can be written on one line, with the values separated by commas: `case 4, 5:`.\n","task":"A weekly pill organizer numbers its boxes from 1 (Monday) to 7 (Sunday). Read a day's number, a whole number on one line, and print the day's name with a switch: `Monday`, `Tuesday`, `Wednesday`, `Thursday`, `Friday`, `Saturday` or `Sunday`. For any other number, print `No such day`. With the input `3`, the program prints:\n\n```\nWednesday\n```\n","kind":"code","seed":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        int day = Integer.valueOf(scanner.nextLine());\n        // print the day's name with a switch\n\n    }\n}\n","solution":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        int day = Integer.valueOf(scanner.nextLine());\n        switch (day) {\n            case 1:\n                System.out.println(\"Monday\");\n                break;\n            case 2:\n                System.out.println(\"Tuesday\");\n                break;\n            case 3:\n                System.out.println(\"Wednesday\");\n                break;\n            case 4:\n                System.out.println(\"Thursday\");\n                break;\n            case 5:\n                System.out.println(\"Friday\");\n                break;\n            case 6:\n                System.out.println(\"Saturday\");\n                break;\n            case 7:\n                System.out.println(\"Sunday\");\n                break;\n            default:\n                System.out.println(\"No such day\");\n        }\n    }\n}\n","hints":["Start with `switch (day) {`, then one `case` per day: `case 1:`, the line that prints `Monday`, and `break;`.","`default:` at the end catches every other number, such as 0 or 9. Check that every case ends with `break;`, or a day prints the next day's name too."],"tests":[{"name":"Test 1","stdin":"3\n","expect":"Wednesday","hidden":false},{"name":"Test 2","stdin":"1\n","expect":"Monday","hidden":true},{"name":"Test 3","stdin":"6\n","expect":"Saturday","hidden":true},{"name":"Test 4","stdin":"7\n","expect":"Sunday","hidden":true},{"name":"Test 5","stdin":"0\n","expect":"No such day","hidden":true},{"name":"Test 6","stdin":"12\n","expect":"No such day","hidden":true}],"require":[{"pattern":"\\bswitch\\s*\\(\\s*day\\s*\\)","message":"Choose the name with `switch (day)`."}],"forbid":[{"pattern":"\\bif\\s*\\(","message":"Use the switch's labels instead of `if`."}],"more":[{"task":"In the board game Ladder Race, a roll of the die decides what you do. The program reads a roll, a whole number on one line, and prints what it means. With a roll of 2 it should print `Pick a card`, but it prints two lines. Find the bug and fix it, keeping the switch. With the input `2`, the program prints:\n\n```\nPick a card\n```\n","kind":"code","seed":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        int roll = Integer.valueOf(scanner.nextLine());\n        switch (roll) {\n            case 1:\n                System.out.println(\"Miss a turn\");\n                break;\n            case 2:\n                System.out.println(\"Pick a card\");\n            case 3:\n                System.out.println(\"Move 3 squares\");\n                break;\n            case 4:\n                System.out.println(\"Swap places with the leader\");\n                break;\n            case 5:\n                System.out.println(\"Move 5 squares\");\n                break;\n            case 6:\n                System.out.println(\"Move 6 squares\");\n                System.out.println(\"Roll again\");\n                break;\n            default:\n                System.out.println(\"Not a roll of a die\");\n        }\n    }\n}\n","solution":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        int roll = Integer.valueOf(scanner.nextLine());\n        switch (roll) {\n            case 1:\n                System.out.println(\"Miss a turn\");\n                break;\n            case 2:\n                System.out.println(\"Pick a card\");\n                break;\n            case 3:\n                System.out.println(\"Move 3 squares\");\n                break;\n            case 4:\n                System.out.println(\"Swap places with the leader\");\n                break;\n            case 5:\n                System.out.println(\"Move 5 squares\");\n                break;\n            case 6:\n                System.out.println(\"Move 6 squares\");\n                System.out.println(\"Roll again\");\n                break;\n            default:\n                System.out.println(\"Not a roll of a die\");\n        }\n    }\n}\n","hints":["Which line does it print after `Pick a card`? That's the first line of the next case: the program fell through into it.","Every case needs a `break;` at its end. One of them doesn't have one."],"tests":[{"name":"Test 1","stdin":"2\n","expect":"Pick a card","hidden":false},{"name":"Test 2","stdin":"1\n","expect":"Miss a turn","hidden":true},{"name":"Test 3","stdin":"3\n","expect":"Move 3 squares","hidden":true},{"name":"Test 4","stdin":"6\n","expect":"Move 6 squares\nRoll again","hidden":true},{"name":"Test 5","stdin":"8\n","expect":"Not a roll of a die","hidden":true}],"require":[{"pattern":"\\bswitch\\s*\\(\\s*roll\\s*\\)","message":"Keep the `switch (roll)`."}],"forbid":[]},{"task":"The pill organizer's reminder now only needs to know the kind of day. Read a day's number (1 is Monday, 7 is Sunday), a whole number on one line, and print `weekday` for 1 to 5, `weekend` for 6 and 7, and `No such day` for any other number. Use a switch where several labels share one branch, so that the program has only three `println` lines. With the input `6`, the program prints:\n\n```\nweekend\n```\n","kind":"code","seed":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        int day = Integer.valueOf(scanner.nextLine());\n\n    }\n}\n","solution":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        int day = Integer.valueOf(scanner.nextLine());\n        switch (day) {\n            case 1, 2, 3, 4, 5:\n                System.out.println(\"weekday\");\n                break;\n            case 6, 7:\n                System.out.println(\"weekend\");\n                break;\n            default:\n                System.out.println(\"No such day\");\n        }\n    }\n}\n","hints":["Labels in a row share the statements after the last of them: `case 6:` followed straight by `case 7:`. Or put the values on one line: `case 6, 7:`.","Days 1 to 5 are one label line too: `case 1, 2, 3, 4, 5:`. Then `default:` for everything else."],"tests":[{"name":"Test 1","stdin":"6\n","expect":"weekend","hidden":false},{"name":"Test 2","stdin":"7\n","expect":"weekend","hidden":true},{"name":"Test 3","stdin":"1\n","expect":"weekday","hidden":true},{"name":"Test 4","stdin":"5\n","expect":"weekday","hidden":true},{"name":"Test 5","stdin":"8\n","expect":"No such day","hidden":true},{"name":"Test 6","stdin":"-1\n","expect":"No such day","hidden":true}],"require":[{"pattern":"\\bswitch\\s*\\(\\s*day\\s*\\)","message":"Choose the kind of day with `switch (day)`."},{"pattern":"System\\.out\\.println","max":3,"message":"Use three `println` lines at most: let the days that print the same word share one branch."}],"forbid":[{"pattern":"\\bif\\s*\\(","message":"Use the switch's labels instead of `if`."}]}]}