{"id":"useful-techniques-enums","slug":"enums","title":"Enums: a fixed set of values","text":"Some values can only be one of a few: a traffic light is red, yellow or green, a cup of coffee is small, medium or large. Module 17's TrafficLight challenge kept its color in a String, `private String color;`, and compared it with `equals`. That works as long as every String is spelled exactly right, but nothing stops a typo:\n\n```java\nString light = \"Green\";\nif (light.equals(\"green\")) {\n    System.out.println(\"Go\");\n} else {\n    System.out.println(\"Stop\");\n}\n```\n\n```output\nStop\n```\n\nThe capital G makes it another String, and neither javac nor the program notices anything wrong. An **enum** (short for *enumerated type*) is a type that lists every value it can have:\n\n```java\npublic enum Light {\n    RED, YELLOW, GREEN\n}\n```\n\n- It's written like a class, with the word `enum` in place of `class`, in a file of its own, `Light.java`.\n- The values are called **constants**. They're separated by commas, and by custom written in capital letters.\n- A variable of type Light can hold one of these three, and nothing else (or `null`, like any object variable).\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Light light = Light.GREEN;\n        System.out.println(light);\n        if (light == Light.GREEN) {\n            System.out.println(\"Go\");\n        }\n        light = Light.RED;\n        System.out.println(light == Light.GREEN);\n    }\n}\n// ==== Light.java ====\npublic enum Light {\n    RED, YELLOW, GREEN\n}\n```\n\n```output\nGREEN\nGo\nfalse\n```\n\n- A constant is written with the enum's name and a dot: `Light.GREEN`.\n- Printing a constant prints its name.\n- Constants are compared with `==`. Each constant is one object, made once, the first time the program uses the enum, so there's never a second GREEN, and `==` is right here, unlike for Strings. (`equals` gives the same answers.)\n\nA typo is now javac's problem, not the user's:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Light light = Light.GREN;\n        System.out.println(light);\n    }\n}\n// ==== Light.java ====\npublic enum Light {\n    RED, YELLOW, GREEN\n}\n```\n\n```javac\nMain.java:3: error: cannot find symbol\n        Light light = Light.GREN;\n                           ^\n  symbol:   variable GREN\n  location: class Light\n1 error\n```\n\n### values(), name() and ordinal()\n\n- `Light.values()` returns an array of all the constants, in the order they're written in the enum. A for-each loop goes through it.\n- `name()` returns a constant's name as a String, such as `\"RED\"`.\n- `ordinal()` returns a constant's position in the enum, counted from 0.\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        for (Light light : Light.values()) {\n            System.out.println(light.ordinal() + \": \" + light.name().toLowerCase());\n        }\n        System.out.println(Light.values().length + \" lights\");\n    }\n}\n// ==== Light.java ====\npublic enum Light {\n    RED, YELLOW, GREEN\n}\n```\n\n```output\n0: red\n1: yellow\n2: green\n3 lights\n```\n\n### An enum is a type\n\nAn enum can be the type of a variable, a parameter, a return value, an instance variable or a list's elements, like any class. A method can check which constant it got:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        System.out.println(canCross(Light.GREEN));\n        System.out.println(canCross(Light.YELLOW));\n    }\n\n    public static boolean canCross(Light light) {\n        return light == Light.GREEN;\n    }\n}\n// ==== Light.java ====\npublic enum Light {\n    RED, YELLOW, GREEN\n}\n```\n\n```output\ntrue\nfalse\n```\n\nJava also has `Light.valueOf(\"RED\")`, which gives the constant with that name. For a text that isn't a constant's name, it stops the program with an error, and part 11 covers handling errors like that.\n","task":"A traffic light in the US goes from green to yellow, from yellow to red, and from red back to green. That's the cycle of module 17's TrafficLight, this time with an enum in place of Strings. `Light.java` is ready. In `Main.java`, write the method `next(Light light)`, which returns the light that comes after the one it's given. Compare the constants with `==`. The check runs:\n\n```java\nSystem.out.println(next(Light.GREEN));\nSystem.out.println(next(Light.YELLOW));\nSystem.out.println(next(Light.RED));\n```\n\nand expects:\n\n```\nYELLOW\nRED\nGREEN\n```\n","kind":"code","seed":"// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        System.out.println(next(Light.GREEN));\n        System.out.println(next(Light.YELLOW));\n        System.out.println(next(Light.RED));\n    }\n\n    public static Light next(Light light) {\n        return light;\n    }\n}\n\n// ==== Light.java ====\npublic enum Light {\n    RED, YELLOW, GREEN\n}\n","solution":"// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        System.out.println(next(Light.GREEN));\n        System.out.println(next(Light.YELLOW));\n        System.out.println(next(Light.RED));\n    }\n\n    public static Light next(Light light) {\n        if (light == Light.GREEN) {\n            return Light.YELLOW;\n        }\n        if (light == Light.YELLOW) {\n            return Light.RED;\n        }\n        return Light.GREEN;\n    }\n}\n\n// ==== Light.java ====\npublic enum Light {\n    RED, YELLOW, GREEN\n}\n","hints":["Check which light the method got with `if (light == Light.GREEN)`, and return the one after it, such as `return Light.YELLOW;`.","Two checks are enough: green gives yellow, yellow gives red, and the only light left, red, gives green."],"tests":[{"name":"Test 1","stdin":"","call":"System.out.println(next(Light.GREEN));\nSystem.out.println(next(Light.YELLOW));\nSystem.out.println(next(Light.RED));\n","expect":"YELLOW\nRED\nGREEN","hidden":false},{"name":"Test 2","stdin":"","call":"Light light = Light.RED;\nfor (int i = 0; i < 4; i++) {\n    light = next(light);\n    System.out.println(light);\n}\nSystem.out.println(next(next(Light.GREEN)) == Light.RED);\n","expect":"GREEN\nYELLOW\nRED\nGREEN\ntrue","hidden":true}],"require":[{"pattern":"==","message":"Compare the constants with `==`, as in `light == Light.GREEN`."}],"forbid":[{"pattern":"\"(RED|YELLOW|GREEN)\"","raw":true,"flags":"i","message":"Use the enum's constants, like `Light.RED`, not Strings."}],"more":[{"task":"What does this program print?\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        Light[] lights = Light.values();\n        Light last = lights[lights.length - 1];\n        System.out.println(last + \" \" + last.ordinal());\n        Light first = Light.RED;\n        Light same = Light.RED;\n        System.out.println(first == same);\n        int letters = 0;\n        for (Light light : lights) {\n            letters += light.name().length();\n        }\n        System.out.println(letters);\n    }\n}\n// ==== Light.java ====\npublic enum Light {\n    RED, YELLOW, GREEN\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Light[] lights = Light.values();\n        Light last = lights[lights.length - 1];\n        System.out.println(last + \" \" + last.ordinal());\n        Light first = Light.RED;\n        Light same = Light.RED;\n        System.out.println(first == same);\n        int letters = 0;\n        for (Light light : lights) {\n            letters += light.name().length();\n        }\n        System.out.println(letters);\n    }\n}\n// ==== Light.java ====\npublic enum Light {\n    RED, YELLOW, GREEN\n}\n","hints":["`values()` gives the constants in the order the enum lists them, so the last one is GREEN, at position 2.","There's only one RED, so both variables refer to it. The names RED, YELLOW and GREEN have 3, 6 and 5 letters."],"tests":[{"name":"Output","stdin":"","expect":"GREEN 2\ntrue\n14","hidden":false}],"require":[],"forbid":[],"lines":["GREEN 2","true","14"]},{"task":"On a parade ground, a marching band faces north, east, south or west, and at the command \"right face\", everyone makes a quarter turn clockwise. Write:\n\n- in `Direction.java`, the enum `Direction`, with the constants `NORTH`, `EAST`, `SOUTH` and `WEST`, in that order (clockwise)\n- in `Main.java`, the method `turnRight(Direction facing)`, which returns the direction after a quarter turn clockwise: north to east, east to south, south to west, and west back to north\n\n`main` is a test drive, and it prints:\n\n```\nNORTH\nEAST\nSOUTH\nWEST\nNORTH\n```\n","kind":"code","seed":"// ==== Direction.java ====\npublic enum Direction {\n\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Direction facing = Direction.NORTH;\n        for (int i = 0; i < 5; i++) {\n            System.out.println(facing);\n            facing = turnRight(facing);\n        }\n    }\n\n    // Write the method turnRight here.\n}\n","solution":"// ==== Direction.java ====\npublic enum Direction {\n    NORTH, EAST, SOUTH, WEST\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Direction facing = Direction.NORTH;\n        for (int i = 0; i < 5; i++) {\n            System.out.println(facing);\n            facing = turnRight(facing);\n        }\n    }\n\n    public static Direction turnRight(Direction facing) {\n        Direction[] all = Direction.values();\n        return all[(facing.ordinal() + 1) % all.length];\n    }\n}\n","hints":["The enum is one line inside its braces: the four constants, separated by commas. The method's header is `public static Direction turnRight(Direction facing)`.","Since the constants are in clockwise order, the next direction is the next constant: `Direction.values()[facing.ordinal() + 1]`, except that after WEST comes NORTH again. `% 4` (or `% values().length`) takes care of that. Three `if`s with `==` work too."],"tests":[{"name":"The test drive","stdin":"","expect":"NORTH\nEAST\nSOUTH\nWEST\nNORTH","hidden":false},{"name":"Test 2","stdin":"","call":"System.out.println(turnRight(Direction.WEST) + \" \" + turnRight(Direction.SOUTH));\nDirection d = Direction.EAST;\nd = turnRight(turnRight(d));\nSystem.out.println(d + \" \" + (d == Direction.WEST) + \" \" + Direction.values().length);\n","expect":"NORTH WEST\nWEST true 4","hidden":true}],"require":[{"pattern":"\\benum\\s+Direction\\b","message":"Write `Direction` as an enum: `public enum Direction { ... }`."},{"pattern":"\\bpublic\\s+static\\s+Direction\\s+turnRight\\s*\\(\\s*Direction\\s+\\w+\\s*\\)","message":"Write the method as `public static Direction turnRight(Direction facing)`."}],"forbid":[]}]}