name: inverse layout: true class: taylor msoe --- class: center, middle .title[ # Exception Handling ] ??? * **P** speaker view * **C** clone slideshow * **?** help --- # Exception Handling * Exception handling is a technique in Java for recovering from exceptional situations -- * Exception handling can make our software more robust -- * A common source of exceptional situation is incorrect/unexpected user input -- * We would like to recover gracefully from incorrect input -- * Typically discover issues with user input in library code (e.g., `Scanner.nextInt()`) -- * Would like to deal with incorrect input at the user interface layer of the code -- * Exceptions allow us to avoid lots of input validation code --- # Exception Handling Mechanics * `throw` when a problem is discovered -- * `catch` where responding to the problem is appropriate -- * When a problem is encountered: + Create an exception + Throw the exception -- * When exception is thrown + Execution in the current method terminates + Exception is thrown to the calling method + Exception continues to be propagated up the calling stack until either - It reaches the JVM (and the program crashes) - It reaches code that is prepared to respond to the exception --- # Catching an Exception * In order to catch an exception, you must `try` ``` Java int weight = -1; do { try { System.out.println("Please enter your weight in lbs"); weight = in.nextInt(); System.out.println("Thank you for entering an integer value"); } catch(InputMismatchException exception) { in.nextLine(); System.out.print("To the nearest integer value... "); } } while(weight<0); ``` --- # Program Flow * If exception is encountered in a `try` block: + Skip any remaining code in the `try` block + Look for matching `catch` block - If found, execute `catch` block and then resume execution **after** the `try`-`catch` block - If not found, exception is immediately thrown up to the calling method -- * Can have multiple `catch` blocks + Must place more specific exceptions first: ``` } catch(ArrayIndexOutOfBoundsException exception) { // ... } catch(IndexOutOfBoundsException exception) { // ... ``` -- * Can have `catch` block with multiple matches, e.g., + `catch(InvalidPathException | NoSuchFileException e)` --- # Checked and Unchecked Exceptions * Checked exceptions must be handled -- * Two ways to handle a checked exception: + Catch the exception + Specify that your method potentially throws the checked exception -- ``` public String readFile(String filename) throws IOException { ``` --- # Common Exceptions .right-column[ * Colored classes indicate Checked exceptions * Should not catch `Error`s ] .left-column[
] --- # Best Practices * Throw exceptions in library code -- * Catch exceptions in user interface code -- * For the MVC pattern: + Throw in Model + Catch in Controller -- * If you can partially handle an exception, can catch and re-throw ``` // ... catch(IOException exception) { LOGGER.log(Level.SEVERE, exception.toString(), exception); throw exception; } ``` -- * Don't catch exceptions if you don't know how to recover -- * Catching an exception can make debugging harder -- * Calling `exception.printStackTrace()` is not handling an exception --- # `finally` Block * The `finally` block is used to force code to run "no matter what" -- * Appears either: .left-column[ After the last `catch` block, or ``` Java try { // ... } catch(NumberFormatException exception) { // ... * } catch(ClassCastException exception) { // ... * } finally { // ... } ``` ] .right-column[ After a `try` block (if there are no `catch` blocks) ``` Java * try { // ... * } finally { // ... } ``` ] --- # Try-with-Resources * Prefer using try-with-resources when possible -- * Applies to any object that implements `Closable` and is needed only within a `try` block ``` Java * try(FileOutputStream out = new FileOutputStream(new File("stuff.txt")); * DataOutputStream dOut = new DataOutputStream(out)) { // ... } catch(FileNotFoundException exception) { // ... } catch(IOException exception) { // ... } ``` --- # Example .left-column[ From [Scanner JavaDoc](https://javadoc.taylorial.com/java.base/util/Scanner.html) ``` Java String input = "1 fish 2 fish red fish blue fish"; Scanner s = null; try { s = new Scanner(input).useDelimiter("\\s*fish\\s*"); System.out.println(s.nextInt()); System.out.println(s.nextInt()); System.out.println(s.next()); System.out.println(s.next()); } finally { if(s!=null) { s.close(); } } ``` ] .right-column[ Output: ``` 1 2 red blue ``` ] ??? * `\\s*fish\\s*` - match on "fish" with zero or more whitespace characters on either side * Java requires the backslash to be escaped (why there are two) --- # Alternative try-with-resources ``` //try { // Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*"); * try(Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*")) { System.out.println(s.nextInt()); System.out.println(s.nextInt()); System.out.println(s.next()); System.out.println(s.next()); //} finally { // if(s!=null) { // s.close(); // } } ``` --- # Recapping * Advantages: * Separate error handling code from other code * Handle exception where it makes sense * Grouping and Differentiating Exception types -- * `Error`s -- serious problem, don't catch -- * `RunTimeException`s -- can occur anywhere, may be numerous -- * All other exceptions are _Checked_ exceptions -- * If you expect calling code to be able to recover from your exception, it should be a checked exception