Java Exceptions (Try ... Catch)
When something goes wrong while a program runs, such as dividing by zero, reading past the end of an array or turning "abc" into a number, Java creates an exception object and throws it. If nothing catches it, the program stops and prints a stack trace. With try and catch your program can handle the problem and carry on.
An uncaught exception
public class Main {
public static void main(String[] args) {
int[] marks = {80, 75, 92};
System.out.println("Before");
System.out.println(marks[5]);
System.out.println("After");
}
}Before Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3 at Main.main(Main.java:5)
Read the stack trace from the top: the first line names the exception and its message, and each at line shows a method and the line number where it was running. Here the problem is on line 5 of Main.java. "After" is never printed: the exception ends main.
try and catch
Put the risky code in a try block and the handling code in a catch block for that kind of exception:
public class Main {
public static void main(String[] args) {
try {
int number = Integer.parseInt("12a");
System.out.println("Number: " + number);
} catch (NumberFormatException e) {
System.out.println("That is not a number: " + e.getMessage());
}
System.out.println("The program goes on.");
}
}That is not a number: For input string: "12a" The program goes on.
When the exception happens, the rest of the try block is skipped and the matching catch block runs. e.getMessage() gives the exception's message.
Several catch blocks and finally
A try can have several catch blocks for different exceptions, and one catch can list several types with |. A finally block runs always, whether an exception happened or not; it is used for clean-up work:
public class Main {
static void divide(String a, String b) {
try {
int x = Integer.parseInt(a), y = Integer.parseInt(b);
System.out.println(x + " / " + y + " = " + x / y);
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero.");
} catch (NumberFormatException | NullPointerException e) {
System.out.println("Bad input: " + e.getClass().getSimpleName());
} finally {
System.out.println("-- done with " + a + " and " + b);
}
}
public static void main(String[] args) {
divide("20", "4");
divide("20", "0");
divide("twenty", "4");
}
}20 / 4 = 5 -- done with 20 and 4 Cannot divide by zero. -- done with 20 and 0 Bad input: NumberFormatException -- done with twenty and 4
Common exceptions
| Exception | Typical cause |
|---|---|
ArithmeticException | whole-number division by zero |
ArrayIndexOutOfBoundsException | an array index outside 0 to length - 1 |
NullPointerException | using a variable that holds null |
NumberFormatException | parseInt on text that is not a number |
InputMismatchException | Scanner.nextInt when the user types a word |
ClassCastException | casting an object to a class it does not belong to |
Asking again after bad input
Combining a while loop with try ... catch gives a program that keeps asking until the input is valid, fixing the problem left open in User Input:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int age = -1;
while (age < 0) {
System.out.print("Your age: ");
String line = in.nextLine();
try {
age = Integer.parseInt(line.strip());
} catch (NumberFormatException e) {
System.out.println("Please type digits only.");
}
}
System.out.println("Thank you, " + age + " noted.");
}
}twenty 20
Your age: Please type digits only. Your age: Thank you, 20 noted.
Catch exceptions you can do something about, and keep the catch blocks specific. Catching everything with catch (Exception e) and doing nothing hides real bugs. The next topic, Throw and Throws, shows how to throw exceptions yourself.
Practice exercises
- Ask for two numbers and divide them, printing a friendly message for division by zero.
- Read an index from the user and print that element of an array, catching a bad index.
- Add a
finallyblock that prints "Goodbye" to one of your programs and check that it always runs.