--- tags: fall 2018 cs61b --- # Exception Notes [TOC] ## Introduction `Throwable` is a superclass with two subclasses, `Error` and `Exception`. `Error` objects indicate serious problems with your application and a reasonable application should not catch one. They are in a separate class from `Exception` because they *cannot* be handled. An example is `OutOfMemoryError`, which cannot be fixed with programming. At this point, we want our program to end to fix it. Also, any exceptions thrown under the `Error` class and its subclasses are considered *unchecked exceptions*. Don’t worry too much about `Error`! It is out of scope. `Exception` objects, on the other hand, can be caught and handled with programming. There are two types of exceptions: 1. **Checked Exceptions:** exceptions that need to be explicitly handled and are caught by the compiler *Examples:* file name is not equal to class name, casting an object to an independent class, symbol not resolved, non-static field/method cannot be referenced from a static context 2. **Unchecked Exceptions:** exceptions that are not caught by the compiler, but thrown during runtime *Examples:* `NullPointerException`, `ArrayIndexOutOfBoundsException`, `ClassCastException` *Note:* These are exception subclasses that explicitly extend the `RuntimeException` class. Also, the class `RuntimeException` extends `Exception`. Any unchecked exception object, disregarding any `Error` object, such as `NullPointerException` extends `RuntimeException`. **Some further clarification:** `Exception` is considered a superclass of all exceptions, unchecked (disregarding `Error` objects) and checked. This means a **catch** block (you'll read about this later) that catches an `Exception` type object could catch checked exceptions. Below is what the Java `Exception` class hierarchy looks like: ![](https://i.imgur.com/KC9kwIw.png) ### Why are exception objects useful? We want to be able to catch and handle exceptions during runtime. This makes debugging easier! Sometimes, programs want to do something with exceptions. Suppose we’re programming a game. If we have any conditions that satisfy game over, we can purposely throw a `RuntimeException`, print out ‘Game Over’, and immediately end the game. ### What actually happens if an exception occurs? Suppose we have a `main` method that calls a `f1` method, which calls a `f2` method and an exception occurs. This creates an `Exception` object that must be handled by the runtime system. What will happen is the runtime system will go down the call stack searching for something that will handle the exception. If it finds nothing, the program will terminate with the exception. If a **try-catch** block catches the exception, then the exception is considered *handled*. ![](https://i.imgur.com/ga6wcWS.png) ## Try-Catch Blocks **Try-catch** blocks in Java are very similar to the **try-catch** blocks you’ve seen in CS 61A! If any code in your **try** block throws an exception, it can be “caught” by a **catch** block! Note: The **catch** blocks would only catch exceptions thrown in the **try** block. If any exceptions are thrown in a **catch** block, the code would terminate with the exception! **Example of Try-Catch Block:** ```Java try { //code that produces the exception throwException(); } catch (NullPointerException e) { //code that handles the specific exception that is thrown } catch (Exception e) { //code that handles any type of exception that is thrown } ``` ### Compile-Time Errors Associated with Try-Catch Consider the following code below and ask if we would ever reach the second **catch** block: ```Java try { throwException(); } catch (Exception e) { System.out.println(”This catch block would catch all exceptions.”); } catch (NullPointerException e) { System.out.println(”This catch block would never be reached.”); } ``` The code above would not compile since all exceptions would be caught by the first **catch** block. Remember: All specific exception classes (such as `NullPointerException`) extend `Exception`. The compiler would complain because the second **catch** block would never run! A general rule of thumb when creating **try-catch** blocks is to catch *specific* errors first before addressing more *general* errors. ### Creating and Throwing Exception Objects ```Java try { throw new RuntimeException(); //the code above is equivalent to: //RuntimeException e = new RuntimeException(); //throw e; } catch (Exception e) { throw e; } ``` Since `RuntimeException` extends `Exception`, the `RuntimeException` would be caught by the **catch** block. In the **catch** block, the same object with static type `RuntimeException` and dynamic type `RuntimeException` will be thrown. ## Resources [CSM Mercantilism Slides](https://docs.google.com/presentation/d/1j418bduZS2Ltm6dVVg-b3WpGbOGrRUm6DKRkZCByuaQ/edit#slide=id.p): comprehensive overview of exceptions and a problem involving exceptions