{"id":"exceptions-checked","slug":"checked-exceptions","title":"Checked exceptions and throws","text":"In module 20, a program that opened a file without a `try` didn't compile: javac said `unreported exception IOException; must be caught or declared to be thrown`. A program that calls `Integer.parseInt` gets no such message, though `parseInt` can throw too. Java treats the two kinds of exceptions differently.\n\n### Checked and unchecked\n\n- **Unchecked exceptions** are RuntimeException and every class below it: NumberFormatException, ArithmeticException, the index exceptions, NullPointerException and the rest. They usually come from a mistake in the program, or from a value it could have checked first. javac leaves them to you: you catch them where you expect them, like text that isn't a number.\n- **Checked exceptions** are all the other Exceptions, such as IOException. They come from things outside the program's control: a file that isn't there, a full disk, a network that's down. However careful the code is, they can happen. So when javac compiles the program, it **checks** that every checked exception is either caught or declared. That's where the name comes from.\n\nA method's documentation lists the checked exceptions it can throw, and javac tells you when you've forgotten one.\n\n`Files.readAllLines` is another way to read a file: it reads all the lines at once and returns them in a `List<String>`. `Files` is in `java.nio.file`, next to `Paths`. This method reads a settings file, with one setting per line, a name and a value with `=` between them, and looks up one setting. It doesn't compile:\n\n```java\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        System.out.println(\"Volume: \" + readSetting(\"settings.txt\", \"volume\"));\n    }\n\n    public static String readSetting(String fileName, String name) {\n        List<String> lines = Files.readAllLines(Paths.get(fileName));\n        for (String line : lines) {\n            String[] parts = line.split(\"=\");\n            if (parts[0].equals(name)) {\n                return parts[1];\n            }\n        }\n        return \"\";\n    }\n}\n```\n\n```javac\nMain.java:11: error: unreported exception IOException; must be caught or declared to be thrown\n        List<String> lines = Files.readAllLines(Paths.get(fileName));\n                                               ^\n1 error\n```\n\n### Declaring it: throws\n\n\"Caught\" you know: a `try` and a `catch` around the line. \"Declared\" is the other choice. The method writes `throws IOException` in its header, after the parameters:\n\n```java\npublic static String readSetting(String fileName, String name) throws IOException {\n```\n\nIt says: this method may throw an IOException, and it doesn't handle it itself; whoever calls it must. The method's code stays as it was. If `readAllLines` throws, `readSetting` stops right there, and the exception goes on to the caller, which then has the same two choices: catch it, or declare it too. Here `main` catches it:\n\n```file settings.txt\nvolume=7\ntheme=dark\n```\n\n```java\nimport java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        String[] files = {\"settings.txt\", \"backup.txt\"};\n        for (String file : files) {\n            try {\n                System.out.println(\"Volume in \" + file + \": \" + readSetting(file, \"volume\"));\n            } catch (IOException e) {\n                System.out.println(\"Could not read \" + file);\n            }\n        }\n    }\n\n    public static String readSetting(String fileName, String name) throws IOException {\n        List<String> lines = Files.readAllLines(Paths.get(fileName));\n        for (String line : lines) {\n            String[] parts = line.split(\"=\");\n            if (parts[0].equals(name)) {\n                return parts[1];\n            }\n        }\n        return \"\";\n    }\n}\n```\n\n```output\nVolume in settings.txt: 7\nCould not read backup.txt\n```\n\n- `IOException` is in the package `java.io`, so it needs an import: `import java.io.IOException;`.\n- There's no `backup.txt`, so `readAllLines` throws, `readSetting` passes the exception on, and `main`'s `catch` block handles it.\n- Who should catch it? The method that knows what to do about it. `readSetting` can't know whether a missing file is an error or just means \"use the defaults\", so it passes the exception on, and `main` decides.\n\n`throws Exception` declares any exception at all. It's shorter, and you'll see it often in small programs, but it tells the caller less, and the caller then has to catch `Exception`, or declare it too.\n\n### An exception travels up\n\nAn exception that isn't caught leaves the method it was thrown in, then the method that called that one, and so on up the call stack, until it reaches a `catch` block that matches. The stack trace of a crash lists exactly those methods. Unchecked exceptions travel the same way, only without any `throws`: javac checks the checked ones alone. So every method a checked exception can pass through must declare it. A method that calls `readSetting` and doesn't catch the IOException needs `throws IOException` in its own header too.\n\n### main throws Exception\n\n`main` can declare exceptions too:\n\n```java\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) throws Exception {\n        List<String> lines = Files.readAllLines(Paths.get(\"settings.txt\"));\n        System.out.println(lines.size() + \" settings\");\n    }\n}\n```\n\n```crash\nException in thread \"main\" java.nio.file.NoSuchFileException: settings.txt\n\tat Main.main(Main.java:7)\n```\n\n`public static void main(String[] args) throws Exception` passes every exception on to whoever called `main`: Java itself. Java handles it the only way it can: the program stops, with the report. Here there's no `settings.txt`, so that's what happens. With the file above, the program would print `2 settings`.\n\nThat's fine for a quick program, or an example where a missing file would be a mistake anyway, and you'll see `main` written this way in many examples, the MOOC's among them. A program for other people should catch the exception and tell them something useful instead.\n","task":"Fill in the blanks, so that `countGuests` passes the IOException on and `main` handles it. The program prints how many names `guests.txt` has, one per line, or `No guest list yet` when the file can't be read (one of the tests gives no file). For the file shown below, it prints:\n\n```\nGuests: 3\n```\n","kind":"fill","seed":"import java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        try {\n            System.out.println(\"Guests: \" + countGuests(\"guests.txt\"));\n        } [[catch]] (IOException e) {\n            System.out.println(\"No guest list yet\");\n        }\n    }\n\n    public static int countGuests(String fileName) [[throws]] IOException {\n        List<String> names = Files.readAllLines(Paths.get(fileName));\n        return names.size();\n    }\n}\n","solution":"import java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        try {\n            System.out.println(\"Guests: \" + countGuests(\"guests.txt\"));\n        } catch (IOException e) {\n            System.out.println(\"No guest list yet\");\n        }\n    }\n\n    public static int countGuests(String fileName) throws IOException {\n        List<String> names = Files.readAllLines(Paths.get(fileName));\n        return names.size();\n    }\n}\n","hints":["The `try` block is followed by the block that runs when the reading fails: `catch`.","A method declares the exceptions it passes on in its header, after the parameters, with the word `throws`."],"tests":[{"name":"Test 1","stdin":"","files":{"guests.txt":"Ines\nTomasz\nPriya\n"},"expect":"Guests: 3","hidden":false},{"name":"Without the file","stdin":"","expect":"No guest list yet","hidden":true},{"name":"Test 3","stdin":"","files":{"guests.txt":"Ada\nGrace\nLinus\nMargaret\nKen\n"},"expect":"Guests: 5","hidden":true}],"require":[],"forbid":[],"more":[{"task":"A writing app counts the words in an essay. The program doesn't compile: javac says `unreported exception IOException` in `countWords`. Make `countWords` pass the exception on with `throws`, and make `main` catch it: when the file can't be read, the program prints `Could not read essay.txt`. `countWords` gets no `try` of its own. For the file shown below, the program prints:\n\n```\nWords: 9\n```\n","kind":"code","seed":"import java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        System.out.println(\"Words: \" + countWords(\"essay.txt\"));\n    }\n\n    public static int countWords(String fileName) {\n        List<String> lines = Files.readAllLines(Paths.get(fileName));\n        int words = 0;\n        for (String line : lines) {\n            words += line.split(\" \").length;\n        }\n        return words;\n    }\n}\n","solution":"import java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        try {\n            System.out.println(\"Words: \" + countWords(\"essay.txt\"));\n        } catch (IOException e) {\n            System.out.println(\"Could not read essay.txt\");\n        }\n    }\n\n    public static int countWords(String fileName) throws IOException {\n        List<String> lines = Files.readAllLines(Paths.get(fileName));\n        int words = 0;\n        for (String line : lines) {\n            words += line.split(\" \").length;\n        }\n        return words;\n    }\n}\n","hints":["Add `throws IOException` to `countWords`'s header, after the parentheses. Then javac's message moves to `main`, which calls it.","In `main`, put the `println` in a `try` block, and print `Could not read essay.txt` in `catch (IOException e)`."],"tests":[{"name":"Test 1","stdin":"","files":{"essay.txt":"Rivers shape the valleys\nover many thousands of years\n"},"expect":"Words: 9","hidden":false},{"name":"Without the file","stdin":"","expect":"Could not read essay.txt","hidden":true},{"name":"Test 3","stdin":"","files":{"essay.txt":"Bees visit flowers\nand carry pollen between them\nas they feed\n"},"expect":"Words: 11","hidden":true}],"require":[{"pattern":"countWords\\s*\\([^)]*\\)\\s*throws\\s+(IOException|Exception)\\b","message":"Declare the exception in `countWords`'s header: `throws IOException`."},{"pattern":"\\btry\\b","min":1,"max":1,"message":"Use one `try`, in `main`. `countWords` passes the exception on instead of catching it."}],"forbid":[]},{"task":"`sum` has no `try`, and an unchecked exception needs no `throws`. What does this program print?\n","kind":"predict","seed":"public class Main {\n    public static void main(String[] args) {\n        System.out.println(total(\"4,5\"));\n        System.out.println(total(\"4,five,6\"));\n    }\n\n    public static int total(String text) {\n        try {\n            return sum(text.split(\",\"));\n        } catch (NumberFormatException e) {\n            System.out.println(\"bad part\");\n            return -1;\n        }\n    }\n\n    public static int sum(String[] parts) {\n        int sum = 0;\n        for (String part : parts) {\n            sum += Integer.parseInt(part);\n            System.out.println(\"added \" + part);\n        }\n        return sum;\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        System.out.println(total(\"4,5\"));\n        System.out.println(total(\"4,five,6\"));\n    }\n\n    public static int total(String text) {\n        try {\n            return sum(text.split(\",\"));\n        } catch (NumberFormatException e) {\n            System.out.println(\"bad part\");\n            return -1;\n        }\n    }\n\n    public static int sum(String[] parts) {\n        int sum = 0;\n        for (String part : parts) {\n            sum += Integer.parseInt(part);\n            System.out.println(\"added \" + part);\n        }\n        return sum;\n    }\n}\n","hints":["When `parseInt(\"five\")` throws, `sum` stops right there: no `added five`, no `6`, and no `return sum`. The exception goes up to `total`, which called `sum` inside its `try` block.","`total`'s `catch` block prints `bad part` and returns -1, which `main` prints."],"tests":[{"name":"Output","stdin":"","expect":"added 4\nadded 5\n9\nadded 4\nbad part\n-1","hidden":false}],"require":[],"forbid":[],"lines":["added 4","added 5","9","added 4","bad part","-1"]}]}