3.4. Handling Exceptions (Try-Catch)

We will continue with the same code example from the last section:

Original Example
public class Exception {
   public static void main(String[] args) {
      exception();
   } // main

   public static void exception() {
      String s = null;

      if (s.length() > 1) {
         System.out.println("string length > 1");
      } // if
   } // exception
} // Exception

To handle the exception in the example above, you need to make use of a special control flow syntax known as a try block or try-catch block. With this syntax, you place code that can throw an exception into the try block, then place code for how you want to deal with the exception in the catch block. These two go together, which is why we often refer to it as a try-catch block. During execution, the try-catch block works as follows:

Try-Catch Semantics

  1. Each line in the try block is executed until an exception object is thrown

  2. When the exception is thrown, the JVM redirects the flow of control into the appropriate catch block. In other words, the code in the try block stops executing and the program jumps to the catch block associated with the type of exception that occurred.

    Note

    A try block can have multiple associated catch blocks. The only catch block that will execute is the one that is associated with the type of exception that is thrown.

  3. After the catch block is executed, the flow of control is redirected immediately after the entire try-catch construct.

Here is an example (Notice that we specify NullPointerException in the catch block:

try {
   if (s.length() > 1) {
      System.out.println("string length > 1");
   } // if
} catch (NullPointerException npe) {
   System.out.println("a NullPointerException was thrown!");
} // try
System.out.println("I will print regardless of the value of s.");

This try-catch block differentiates itself from the previous examples in two ways:

  1. we did not perform any condition checking for the exceptional situation–in this case, we did not compare the value of s to null; and

  2. the exception is still reported, however, it’s done so using code that we wrote (and, therefore, can customize) and using code that does not necessarily cause the program to abruptly terminate.

Here is a video with a larger code example demonstrating the benefits of handling exceptions instead of trying to avoid them:

https://www.youtube.com/watch?v=TETdh48t4YM

IMAGE ALT TEXT

Learn by Experimenting!

Using the try-catch semantics as a guide, try to predict the output from each of the programs below. Then, quickly test your answers by compiling/running the programs on Odin.

  1. What is the full the output of the following program?

    public class DivisionExample {
       public static void main(String[] args) {
          int a = 10;
          int b = 2;
    
          try {
             int result = a / b;
             System.out.println("Result: " + result);
          } catch (ArithmeticException e) {
             System.out.println("Cannot divide by zero!");
          } // try
       } // main
    } // DivisionExample
    
  2. What would be the output of the program above if we changed variable b to have a value of 0 instead of 2?

  3. What is the full output of the following program?

    public class MultipleCatchExample {
       public static void main(String[] args) {
          try {
             int[] array = {1, 2, 3};   // 1
             int a = 10, b = 0;         // 2
             String str = null;         // 3
    
             int result = a / b;
    
             System.out.println("Array element: " + array[5]);
             System.out.println("String length: " + str.length());
    
          } catch (ArithmeticException ae) {
             System.out.println("Cannot divide by zero.");
          } catch (ArrayIndexOutOfBoundsException aioobe) {
             System.out.println("Invalid array index.");
          } catch (NullPointerException e) {
             System.out.println("Cannot call a method on a null reference.");
          } // try
    
          System.out.println("Got to the end!");
       } // main
    } // MultipleCatchExample
    
  4. Change the values assigned to the variables declared on the lines marked 1, 2, and 3 so that no exceptions are thrown and the program only prints “Got to the end!”.

  5. Is it possible to make the program print both “Invalid array index.” and “Cannot divide by zero.” only by changing the values assigned in the lines marked 1, 2, and 3? If so, how would you do it? If not, explain why not.

Remember to check your answers by running the code on Odin. We encourage you to explore other questions that may arise while working through these. As always, post any questions you have on the course Piazza page. Posting questions/answers to questions found in the reading is encouraged!