{"id":"generics-why","slug":"why-type-parameters","title":"Why type parameters","text":"Since module 13 you've written types like `ArrayList<String>` and `ArrayList<Integer>`, and since module 31 `HashMap<String, Integer>`. ArrayList is one class, written once by Java's developers. Yet each list knows the type of its values: `get` on an `ArrayList<String>` gives a String, `get` on an `ArrayList<Integer>` gives an Integer, and adding a number to a list of Strings doesn't compile. The type in the angle brackets makes that work. This module shows how to write classes like that yourself.\n\n### A box for one type\n\nA storeroom keeps things in boxes, one thing per box. Here's a class for a box that holds a String:\n\n```java\npublic class StringBox {\n    private String content;\n\n    public StringBox(String content) {\n        this.content = content;\n    }\n\n    public String getContent() {\n        return this.content;\n    }\n}\n```\n\nA box for a number would be the same class again, with `Integer` in place of `String` in three places. A box for a Book, once more. The code would be the same each time, and only the type would change.\n\n### Why not Object?\n\nEvery class inherits from Object (module 34), so a box whose content is an Object takes anything. But then what comes out is just an Object, and Java no longer knows what kind:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        ObjectBox box = new ObjectBox(\"tent pegs\");\n        String content = box.getContent();\n        System.out.println(content.toUpperCase());\n    }\n}\n// ==== ObjectBox.java ====\npublic class ObjectBox {\n    private Object content;\n\n    public ObjectBox(Object content) {\n        this.content = content;\n    }\n\n    public Object getContent() {\n        return this.content;\n    }\n\n    public void setContent(Object content) {\n        this.content = content;\n    }\n}\n```\n\n```javac\nMain.java:4: error: incompatible types: Object cannot be converted to String\n        String content = box.getContent();\n                                       ^\n1 error\n```\n\nYou know there's a String in the box, but the compiler only knows that `getContent()` returns an Object. A cast, `(String) box.getContent()`, would make it compile (module 36). But nothing stops other code from putting a number into that box, and then the cast fails while the program runs, with a ClassCastException.\n\n### A type parameter\n\nThe way out is to let the code that creates a box say what goes in it. The class gets a **type parameter**, written in angle brackets after its name:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        Box<String> pegs = new Box<String>(\"tent pegs\");\n        System.out.println(pegs.getContent().toUpperCase());\n\n        Box<Integer> coins = new Box<Integer>(340);\n        int total = coins.getContent() + 25;\n        System.out.println(total);\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```output\nTENT PEGS\n365\n```\n\n- `public class Box<T>` says that Box has a type parameter called T. T stands for a type that isn't decided yet: each box decides it when it's created.\n- Inside the class, T is used like any other type: for the instance variable, `private T content;`, for the constructor's parameter, as the return type of `getContent`, and as the type of `setContent`'s parameter.\n- `Box<String>` is a box whose T is String. For this box, `getContent()` returns a String, so `toUpperCase()` works without a cast. `coins` is a `Box<Integer>`, so its `getContent()` returns an Integer, which can be added to.\n- The constructor's header is `public Box(T content)`. The `<T>` comes only after the class's name in the class header, never after the constructor's name.\n\nYou can picture it like this: when Java checks code that uses a `Box<String>`, it reads every T in Box as String. One class, written once, works for any type. That's how ArrayList is written too: its header begins `public class ArrayList<E>`, and its `get` returns an E.\n\n### Naming a type parameter\n\nA type parameter can have any name, but the custom is a single capital letter, so that it's easy to tell from a class's name: `T` for \"type\", `E` for \"element\" (Java's lists use it), and `K` and `V` for \"key\" and \"value\" (HashMap uses them).\n","task":"A learning app shows a word of the day and a number of the day, with one class for both. Fill in the three blanks so that `Featured` works for any type: the type parameter in the class header, the type of the instance variable, and the return type of `get`. The program prints:\n\n```\nWord of the day: lantern (7 letters)\nNumber of the day: 64, half of it is 32\n```\n","kind":"fill","seed":"public class Main {\n    public static void main(String[] args) {\n        Featured<String> word = new Featured<String>(\"lantern\");\n        System.out.println(\"Word of the day: \" + word.get() + \" (\" + word.get().length() + \" letters)\");\n\n        Featured<Integer> number = new Featured<Integer>(64);\n        System.out.println(\"Number of the day: \" + number.get() + \", half of it is \" + number.get() / 2);\n    }\n}\n// ==== Featured.java ====\npublic class Featured<[[T]]> {\n    private [[T]] item;\n\n    public Featured(T item) {\n        this.item = item;\n    }\n\n    public [[T]] get() {\n        return this.item;\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        Featured<String> word = new Featured<String>(\"lantern\");\n        System.out.println(\"Word of the day: \" + word.get() + \" (\" + word.get().length() + \" letters)\");\n\n        Featured<Integer> number = new Featured<Integer>(64);\n        System.out.println(\"Number of the day: \" + number.get() + \", half of it is \" + number.get() / 2);\n    }\n}\n// ==== Featured.java ====\npublic class Featured<T> {\n    private T item;\n\n    public Featured(T item) {\n        this.item = item;\n    }\n\n    public T get() {\n        return this.item;\n    }\n}\n","hints":["The constructor's parameter is already written as `T item`. What does that tell you about the type parameter's name?","The instance variable holds a T, and `get` returns it, so both of the other blanks are `T` too. With `Object` there, `word.get().length()` wouldn't compile."],"tests":[{"name":"Output","stdin":"","expect":"Word of the day: lantern (7 letters)\nNumber of the day: 64, half of it is 32","hidden":false}],"require":[],"forbid":[],"more":[{"task":"Two boxes from the storeroom both hold a seven: one as a String, the other as an Integer. `Box` is the class from this step. What does this program print?\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        Box<String> label = new Box<String>(\"7\");\n        Box<Integer> count = new Box<Integer>(7);\n        System.out.println(label.getContent() + 1);\n        System.out.println(count.getContent() + 1);\n        label.setContent(label.getContent() + count.getContent());\n        count.setContent(count.getContent() * 2);\n        System.out.println(label.getContent() + \" \" + count.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":"public class Main {\n    public static void main(String[] args) {\n        Box<String> label = new Box<String>(\"7\");\n        Box<Integer> count = new Box<Integer>(7);\n        System.out.println(label.getContent() + 1);\n        System.out.println(count.getContent() + 1);\n        label.setContent(label.getContent() + count.getContent());\n        count.setContent(count.getContent() * 2);\n        System.out.println(label.getContent() + \" \" + count.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":["For `label`, a `Box<String>`, `getContent()` returns a String, and a String plus a number joins them: `\"7\" + 1` is `71`. For `count`, a `Box<Integer>`, it returns an Integer, so `+ 1` adds.","`label.getContent() + count.getContent()` is a String plus an Integer, which joins them into `77`. `count` doubles to 14."],"tests":[{"name":"Output","stdin":"","expect":"71\n8\n77 14","hidden":false}],"require":[],"forbid":[],"lines":["71","8","77 14"]},{"task":"A sports club's trophies pass from holder to holder. The chess trophy goes to a player, given by name. The relay shield goes to a team, given by its number. In `Trophy.java`, write the class `Trophy<T>` with:\n\n- a constructor `Trophy(String name, T holder)`: the trophy's name and its first holder\n- `getHolder()`, which returns the current holder\n- `passTo(T newHolder)`, which makes `newHolder` the holder, and returns the holder before it\n- `toString()`, which returns the trophy's name, a colon and the holder, like `Chess Cup: Ravi`\n\nThe name is always a String; only the holder's type changes. The check runs:\n\n```java\nTrophy<String> chess = new Trophy<String>(\"Chess Cup\", \"Ada\");\nString before = chess.passTo(\"Ravi\");\nSystem.out.println(before + \" passed it on\");\nSystem.out.println(chess);\nTrophy<Integer> relay = new Trophy<Integer>(\"Relay Shield\", 4);\nint old = relay.passTo(7);\nSystem.out.println(old + relay.getHolder());\nSystem.out.println(relay);\n```\n\nand expects:\n\n```\nAda passed it on\nChess Cup: Ravi\n11\nRelay Shield: 7\n```\n","kind":"code","seed":"// ==== Trophy.java ====\npublic class Trophy {\n\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Trophy<String> chess = new Trophy<String>(\"Chess Cup\", \"Ada\");\n        String before = chess.passTo(\"Ravi\");\n        System.out.println(before + \" passed it on\");\n        System.out.println(chess);\n        Trophy<Integer> relay = new Trophy<Integer>(\"Relay Shield\", 4);\n        int old = relay.passTo(7);\n        System.out.println(old + relay.getHolder());\n        System.out.println(relay);\n    }\n}\n","solution":"// ==== Trophy.java ====\npublic class Trophy<T> {\n    private String name;\n    private T holder;\n\n    public Trophy(String name, T holder) {\n        this.name = name;\n        this.holder = holder;\n    }\n\n    public T getHolder() {\n        return this.holder;\n    }\n\n    public T passTo(T newHolder) {\n        T previous = this.holder;\n        this.holder = newHolder;\n        return previous;\n    }\n\n    @Override\n    public String toString() {\n        return this.name + \": \" + this.holder;\n    }\n}\n\n// ==== Main.java ====\npublic class Main {\n    public static void main(String[] args) {\n        Trophy<String> chess = new Trophy<String>(\"Chess Cup\", \"Ada\");\n        String before = chess.passTo(\"Ravi\");\n        System.out.println(before + \" passed it on\");\n        System.out.println(chess);\n        Trophy<Integer> relay = new Trophy<Integer>(\"Relay Shield\", 4);\n        int old = relay.passTo(7);\n        System.out.println(old + relay.getHolder());\n        System.out.println(relay);\n    }\n}\n","hints":["The header is `public class Trophy<T>`. The class has two instance variables: `private String name;` and `private T holder;`. The constructor is `public Trophy(String name, T holder)`, without `<T>`.","`passTo` returns a T and takes a T: `public T passTo(T newHolder)`. Keep the old holder in a variable first, `T previous = this.holder;`, then set the new one, and return `previous`."],"tests":[{"name":"Test 1","stdin":"","call":"Trophy<String> chess = new Trophy<String>(\"Chess Cup\", \"Ada\");\nString before = chess.passTo(\"Ravi\");\nSystem.out.println(before + \" passed it on\");\nSystem.out.println(chess);\nTrophy<Integer> relay = new Trophy<Integer>(\"Relay Shield\", 4);\nint old = relay.passTo(7);\nSystem.out.println(old + relay.getHolder());\nSystem.out.println(relay);\n","expect":"Ada passed it on\nChess Cup: Ravi\n11\nRelay Shield: 7","hidden":false},{"name":"Test 2","stdin":"","call":"Trophy<String> quiz = new Trophy<String>(\"Quiz Bowl\", \"Room 12\");\nSystem.out.println(quiz.getHolder());\nSystem.out.println(quiz.passTo(\"Room 3\") + \" then \" + quiz.passTo(\"Room 7\") + \" then \" + quiz.getHolder());\nSystem.out.println(quiz);\nTrophy<Double> fastest = new Trophy<Double>(\"Fastest Lap\", 72.4);\ndouble previous = fastest.passTo(70.9);\nSystem.out.println(previous - fastest.getHolder() > 1);\nSystem.out.println(fastest);\n","expect":"Room 12\nRoom 12 then Room 3 then Room 7\nQuiz Bowl: Room 7\ntrue\nFastest Lap: 70.9","hidden":true}],"require":[],"forbid":[]}]}