{"id":"generics-type-arguments","slug":"type-arguments","title":"One class, many types","text":"Step 1's Box is one class, and every box chooses its own type. This step shows boxes of more types, a shorter way to create them, and the one kind of type that can't go in the angle brackets.\n\n### Parameter and argument\n\nIn `public class Box<T>`, T is the **type parameter**. In `Box<String>`, String is the **type argument**: the type that T stands for in that box. It's the same pair of words as for methods: a method has a parameter, and each call gives it an argument. A class has a type parameter, and each use of it gives a type argument.\n\n### The diamond\n\n`Box<String> pegs = new Box<String>(\"tent pegs\");` names String twice. Java can work out the second one from the variable's type, so you can leave it out and keep only the angle brackets:\n\n```java\nBox<String> pegs = new Box<>(\"tent pegs\");\n```\n\nThe empty `<>` is called the **diamond**, after its shape. You've written it since module 13, in `new ArrayList<>()`. It works wherever Java can see which type is needed: in a variable's declaration, as here, and also in `return new Box<>(...)` in a method whose return type is, say, `Box<String>`. From here on, this module writes the diamond.\n\nLeave out the angle brackets completely, as in `new Box(\"tent pegs\")`, and you get an old form from before Java had type parameters. javac compiles it, but it adds a note that the program \"uses unchecked or unsafe operations\", because it can no longer check the types. Write at least the `<>`.\n\n### Any class or interface will do\n\nA type argument can be any class or interface: one of Java's own, one of yours, even a type with a type argument of its own:\n\n```java\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        Box<Double> paint = new Box<>(2.5);\n        Box<PowerTool> drill = new Box<>(new PowerTool(\"cordless drill\", 1.8));\n        Box<ArrayList<String>> camping = new Box<>(new ArrayList<>());\n        camping.getContent().add(\"tent\");\n        camping.getContent().add(\"lantern\");\n\n        System.out.println(paint.getContent() * 2 + \" liters of paint\");\n        System.out.println(drill.getContent().getName() + \", \" + drill.getContent().getKilos() + \" kg\");\n        System.out.println(camping.getContent().size() + \" things: \" + camping.getContent());\n    }\n}\n// ==== Box.java ====\npublic class Box<T> {\n    private T content;\n\n    public Box(T content) {\n        this.content = content;\n    }\n\n    public T getContent() {\n        return this.content;\n    }\n\n    public void setContent(T content) {\n        this.content = content;\n    }\n}\n// ==== PowerTool.java ====\npublic class PowerTool {\n    private String name;\n    private double kilos;\n\n    public PowerTool(String name, double kilos) {\n        this.name = name;\n        this.kilos = kilos;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public double getKilos() {\n        return this.kilos;\n    }\n}\n```\n\n```output\n5.0 liters of paint\ncordless drill, 1.8 kg\n2 things: [tent, lantern]\n```\n\n- For `drill`, a `Box<PowerTool>`, `getContent()` returns a PowerTool, so the PowerTool's own methods can be called on it.\n- `Box<ArrayList<String>>` is a box whose T is `ArrayList<String>`. Its `getContent()` returns the list itself, not a copy, so `add` puts the tent and the lantern into the list in the box. Module 33's `HashMap<String, ArrayList<String>>` nested types the same way.\n- In `new Box<>(new ArrayList<>())`, both diamonds are worked out from the variable's type.\n\n### Integer, not int\n\nModule 13 showed that a list can't hold `int`s. A type argument can't be a primitive type at all, for your classes or Java's:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Box<int> chairs = new Box<>(12);\n        System.out.println(chairs.getContent());\n    }\n}\n// ==== Box.java ====\npublic class Box<T> {\n    private T content;\n\n    public Box(T content) {\n        this.content = content;\n    }\n\n    public T getContent() {\n        return this.content;\n    }\n\n    public void setContent(T content) {\n        this.content = content;\n    }\n}\n```\n\n```javac\nMain.java:3: error: unexpected type\n        Box<int> chairs = new Box<>(12);\n            ^\n  required: reference\n  found:    int\n1 error\n```\n\nA type argument must be a reference type (module 22): a class, an interface, even an array type, never a primitive type. That's what javac's `required: reference` means. For a primitive type, use its object partner, its **wrapper class**:\n\n| primitive type | type argument |\n| --- | --- |\n| `int` | `Integer` |\n| `double` | `Double` |\n| `boolean` | `Boolean` |\n| `char` | `Character` |\n\nThat's why it's `List<Integer>`, never `List<int>`. Java converts between the two by itself, as it does with lists: `new Box<>(12)` for a `Box<Integer>` turns 12 into an Integer, and `int chairs = box.getContent();` turns it back into an int. It converts only between a primitive type and its own partner, though: a `Box<Double>` takes `2.0`, but not `2`.\n","task":"The storeroom's app keeps three boxes: the number of screws left, the liters of paint left, and whether the box of fuses is still sealed. Fill in the three type arguments. The program prints:\n\n```\nThe fuses are still sealed\n210 screws\n1.75 liters of paint\n```\n","kind":"fill","seed":"public class Main {\n    public static void main(String[] args) {\n        Box<[[Integer]]> screws = new Box<>(250);\n        Box<[[Double]]> paint = new Box<>(3.5);\n        Box<[[Boolean]]> sealed = new Box<>(true);\n\n        screws.setContent(screws.getContent() - 40);\n        paint.setContent(paint.getContent() / 2);\n        if (sealed.getContent()) {\n            System.out.println(\"The fuses are still sealed\");\n        }\n        System.out.println(screws.getContent() + \" screws\");\n        System.out.println(paint.getContent() + \" liters of paint\");\n    }\n}\n// ==== Box.java ====\npublic class Box<T> {\n    private T content;\n\n    public Box(T content) {\n        this.content = content;\n    }\n\n    public T getContent() {\n        return this.content;\n    }\n\n    public void setContent(T content) {\n        this.content = content;\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Box<Integer> screws = new Box<>(250);\n        Box<Double> paint = new Box<>(3.5);\n        Box<Boolean> sealed = new Box<>(true);\n\n        screws.setContent(screws.getContent() - 40);\n        paint.setContent(paint.getContent() / 2);\n        if (sealed.getContent()) {\n            System.out.println(\"The fuses are still sealed\");\n        }\n        System.out.println(screws.getContent() + \" screws\");\n        System.out.println(paint.getContent() + \" liters of paint\");\n    }\n}\n// ==== Box.java ====\npublic class Box<T> {\n    private T content;\n\n    public Box(T content) {\n        this.content = content;\n    }\n\n    public T getContent() {\n        return this.content;\n    }\n\n    public void setContent(T content) {\n        this.content = content;\n    }\n}\n","hints":["A type argument must be a reference type (a class, an interface or an array type, never a primitive type), so `int`, `double` and `boolean` won't do. Each primitive type has a wrapper class, written with a capital letter.","The screws are a whole number, `Integer`; the paint has decimals, `Double`; and sealed is true or false, `Boolean`."],"tests":[{"name":"Output","stdin":"","expect":"The fuses are still sealed\n210 screws\n1.75 liters of paint","hidden":false}],"require":[],"forbid":[],"more":[{"task":"A scout troop packs for a camping trip. `Box` is the class from this module. Look at the types, and at which list each box holds. What does this program print?\n","kind":"predict","seed":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        Box<Integer> tents = new Box<>(5);\n        Box<Double> water = new Box<>(5.0);\n        tents.setContent(tents.getContent() / 2);\n        water.setContent(water.getContent() / 2);\n        System.out.println(tents.getContent() + \" \" + water.getContent());\n\n        ArrayList<String> gear = new ArrayList<>();\n        Box<ArrayList<String>> red = new Box<>(gear);\n        Box<ArrayList<String>> blue = new Box<>(gear);\n        red.getContent().add(\"rope\");\n        blue.getContent().add(\"stakes\");\n        System.out.println(red.getContent().size() + \" \" + blue.getContent());\n    }\n}\n// ==== Box.java ====\npublic class Box<T> {\n    private T content;\n\n    public Box(T content) {\n        this.content = content;\n    }\n\n    public T getContent() {\n        return this.content;\n    }\n\n    public void setContent(T content) {\n        this.content = content;\n    }\n}\n","solution":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        Box<Integer> tents = new Box<>(5);\n        Box<Double> water = new Box<>(5.0);\n        tents.setContent(tents.getContent() / 2);\n        water.setContent(water.getContent() / 2);\n        System.out.println(tents.getContent() + \" \" + water.getContent());\n\n        ArrayList<String> gear = new ArrayList<>();\n        Box<ArrayList<String>> red = new Box<>(gear);\n        Box<ArrayList<String>> blue = new Box<>(gear);\n        red.getContent().add(\"rope\");\n        blue.getContent().add(\"stakes\");\n        System.out.println(red.getContent().size() + \" \" + blue.getContent());\n    }\n}\n// ==== Box.java ====\npublic class Box<T> {\n    private T content;\n\n    public Box(T content) {\n        this.content = content;\n    }\n\n    public T getContent() {\n        return this.content;\n    }\n\n    public void setContent(T content) {\n        this.content = content;\n    }\n}\n","hints":["`tents` is a `Box<Integer>`, so `getContent() / 2` divides two whole numbers, and the decimals are dropped. `water` is a `Box<Double>`, so its division keeps them.","`red` and `blue` are two boxes, but both hold the same list, `gear`: a box keeps a reference to the list, not a copy (module 22). Both `add`s go into that one list."],"tests":[{"name":"Output","stdin":"","expect":"2 2.5\n2 [rope, stakes]","hidden":false}],"require":[],"forbid":[],"lines":["2 2.5","2 [rope, stakes]"]},{"task":"The storeroom keeps screws in several boxes, each a `Box<Integer>` holding how many screws it has. `Box.java` is ready. In `Main.java`, write two methods:\n\n- `total(ArrayList<Box<Integer>> boxes)`, which returns the number of screws in all the boxes together\n- `fullest(ArrayList<Box<Integer>> boxes)`, which returns the box with the most screws, the first of them if several have the most. The list has at least one box.\n\nThe check runs:\n\n```java\nArrayList<Box<Integer>> boxes = new ArrayList<>();\nboxes.add(new Box<>(120));\nboxes.add(new Box<>(450));\nboxes.add(new Box<>(80));\nSystem.out.println(total(boxes));\nBox<Integer> most = fullest(boxes);\nSystem.out.println(most.getContent());\nmost.setContent(0);\nSystem.out.println(total(boxes));\n```\n\nand expects:\n\n```\n650\n450\n200\n```\n","kind":"code","seed":"// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Box<Integer>> boxes = new ArrayList<>();\n        boxes.add(new Box<>(120));\n        boxes.add(new Box<>(450));\n        boxes.add(new Box<>(80));\n        System.out.println(total(boxes));\n        Box<Integer> most = fullest(boxes);\n        System.out.println(most.getContent());\n        most.setContent(0);\n        System.out.println(total(boxes));\n    }\n\n    // Write the methods total and fullest here.\n}\n\n// ==== Box.java ====\npublic class Box<T> {\n    private T content;\n\n    public Box(T content) {\n        this.content = content;\n    }\n\n    public T getContent() {\n        return this.content;\n    }\n\n    public void setContent(T content) {\n        this.content = content;\n    }\n}\n","solution":"// ==== Main.java ====\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Box<Integer>> boxes = new ArrayList<>();\n        boxes.add(new Box<>(120));\n        boxes.add(new Box<>(450));\n        boxes.add(new Box<>(80));\n        System.out.println(total(boxes));\n        Box<Integer> most = fullest(boxes);\n        System.out.println(most.getContent());\n        most.setContent(0);\n        System.out.println(total(boxes));\n    }\n\n    public static int total(ArrayList<Box<Integer>> boxes) {\n        int sum = 0;\n        for (Box<Integer> box : boxes) {\n            sum += box.getContent();\n        }\n        return sum;\n    }\n\n    public static Box<Integer> fullest(ArrayList<Box<Integer>> boxes) {\n        Box<Integer> most = boxes.get(0);\n        for (Box<Integer> box : boxes) {\n            if (box.getContent() > most.getContent()) {\n                most = box;\n            }\n        }\n        return most;\n    }\n}\n\n// ==== Box.java ====\npublic class Box<T> {\n    private T content;\n\n    public Box(T content) {\n        this.content = content;\n    }\n\n    public T getContent() {\n        return this.content;\n    }\n\n    public void setContent(T content) {\n        this.content = content;\n    }\n}\n","hints":["The headers are `public static int total(ArrayList<Box<Integer>> boxes)` and `public static Box<Integer> fullest(ArrayList<Box<Integer>> boxes)`. A for-each loop goes through the boxes: `for (Box<Integer> box : boxes)`.","In `total`, add each `box.getContent()` to an int sum: Java turns the Integer into an int. In `fullest`, start with `boxes.get(0)` and replace it only when a box has strictly more, `>`, so the first of several fullest boxes stays."],"tests":[{"name":"Test 1","stdin":"","call":"ArrayList<Box<Integer>> boxes = new ArrayList<>();\nboxes.add(new Box<>(120));\nboxes.add(new Box<>(450));\nboxes.add(new Box<>(80));\nSystem.out.println(total(boxes));\nBox<Integer> most = fullest(boxes);\nSystem.out.println(most.getContent());\nmost.setContent(0);\nSystem.out.println(total(boxes));\n","expect":"650\n450\n200","hidden":false},{"name":"Test 2","stdin":"","call":"ArrayList<Box<Integer>> boxes = new ArrayList<>();\nboxes.add(new Box<>(35));\nSystem.out.println(total(boxes) + \" \" + fullest(boxes).getContent());\nboxes.add(new Box<>(90));\nboxes.add(new Box<>(12));\nboxes.add(new Box<>(90));\nSystem.out.println(total(boxes));\nSystem.out.println(fullest(boxes) == boxes.get(1));\nSystem.out.println(fullest(boxes) == boxes.get(3));\n","expect":"35 35\n227\ntrue\nfalse","hidden":true},{"name":"Test 3","stdin":"","call":"ArrayList<Box<Integer>> boxes = new ArrayList<>();\nboxes.add(new Box<>(0));\nboxes.add(new Box<>(0));\nSystem.out.println(total(boxes));\nSystem.out.println(fullest(boxes) == boxes.get(0));\n","expect":"0\ntrue","hidden":true}],"require":[],"forbid":[]}]}