3.5. 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
Each line in the
tryblock is executed until an exception object is thrown. If an exception is not thrown, thetryblock completes normally and the code in thecatchblock(s) is not executed.If an exception is thrown from within the
tryblock, the JVM redirects the flow of control into the appropriate matchingcatchblock. In other words, the code in thetryblock stops executing and the program jumps to thecatchblock associated with the type of exception that occurred.Note
A
tryblock can have multiple associatedcatchblocks. The onlycatchblock that will execute is the one that is associated with the type of exception that is thrown.After the
catchblock 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) {
// Prints only when s != null
System.out.println("string length > 1");
} // if
} catch (NullPointerException npe) {
// Prints only when s == null
System.out.println("a NullPointerException was thrown!");
} // try
// Always prints
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:
we did not perform any condition checking for the exceptional situation–in this case, we did not compare the value of
stonull; andthe 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
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.
What is the full the output of the following program?
1public class DivisionExample { 2 public static void main(String[] args) { 3 int a = 10; 4 int b = 2; 5 6 try { 7 int result = a / b; 8 System.out.println("Result: " + result); 9 } catch (ArithmeticException e) { 10 System.out.println("Cannot divide by zero!"); 11 } // try 12 } // main 13} // DivisionExample
What would be the output of the program above if we changed variable
bto have a value of0instead of2?What is the full output of the following program?
1public class MultipleCatchExample { 2 public static void main(String[] args) { 3 try { 4 int[] array = {1, 2, 3}; // 1 5 int a = 10, b = 0; // 2 6 String str = null; // 3 7 8 int result = a / b; 9 10 System.out.println("Array element: " + array[5]); 11 System.out.println("String length: " + str.length()); 12 13 } catch (ArithmeticException ae) { 14 System.out.println("Cannot divide by zero."); 15 } catch (ArrayIndexOutOfBoundsException aioobe) { 16 System.out.println("Invalid array index."); 17 } catch (NullPointerException e) { 18 System.out.println("Cannot call a method on a null reference."); 19 } // try 20 21 System.out.println("Got to the end!"); 22 } // main 23} // MultipleCatchExample
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 output from the two print statements in the
tryblock along with “Got to the end!” from the final print statement.It is not 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. Why is this not possible?
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!
When handling exceptions, you should be careful that the exceptions you are catching match the exception being thrown.
Important
Double-check that you are catching the appropriate exception(s). Always
carefully consider the code within the try block and which
exceptions are possible. Then, catch each one separately.
For example, try to predict the output of the code below. Are we handling all possible exceptions? Once you have come up with an answer, check yourself with the solution or run the code on Odin.
1public class MultipleCatchExample {
2 public static void main(String[] args) {
3
4 String[] array = {"Hello", "1302", "Students"};
5
6 try {
7 MultipleCatchExample.printIntegers(array);
8 } catch (NullPointerException e) {
9 System.out.println("Invalid input.");
10 } // try
11
12 System.out.println("Got to the end!");
13 } // main
14
15 /**
16 * Prints the first five characters of each string in the
17 * specified array.
18 *
19 * @param strs the specified array
20 * @throws IndexOutOfBoundsException if the string has fewer than
21 * three characters.
22 * @throws NullPointerException if the specified array is {@code null}.
23 */
24 public static void printIntegers(String[] strs) {
25
26 for (int i = 0; i < strs.length; i++) {
27 System.out.println(strs[i].substring(0, 5));
28 } // for
29
30 } // printIntegers
31} // MultipleCatchExample
Solution
The output is:
Hello
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: begin 0, end 5, length 4
at java.base/java.lang.String.checkBoundsBeginEnd(String.java:4604)
at java.base/java.lang.String.substring(String.java:2707)
at MultipleCatchExample.printIntegers(MultipleCatchExample.java:27)
at MultipleCatchExample.main(MultipleCatchExample.java:7)
Notice how the first output, “Hello”, comes out fine. However, the second
causes an exception. The exception that is thrown, StringIndexOutOfBoundsException,
is never caught by our program. We only handle the case
when the array is null.