Exception-Handling Overview
Paul Ngugi
Posted on June 14, 2024
Exception handling enables a program to deal with exceptional situations and continue its normal execution. Runtime errors occur while a program is running if the JVM detects an operation that is impossible to carry out. For example, if you access an array using an index that is out of bounds, you will get a runtime error with an ArrayIndexOutOfBoundsException. If you enter a double value when your program expects an integer, you will get a runtime error with an InputMismatchException.
In Java, runtime errors are thrown as exceptions. An exception is an object that represents an error or a condition that prevents execution from proceeding normally. If the exception is not handled, the program will terminate abnormally. How can you handle the exception so that the program can continue to run or else terminate gracefully?
Exceptions are thrown from a method. The caller of the method can catch and handle the exception. To demonstrate exception handling, including how an exception object is created and thrown, let’s begin with the example in program below, which reads in two integers and displays their
quotient.
Enter two integers: 5 2
5 / 2 is 2
Enter two integers: 3 0
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Quotient.main(Quotient.java:11)
If you entered 0 for the second number, a runtime error would occur, because you cannot divide an integer by 0. (Note that a floating-point number divided by 0 does not raise an exception.) A simple way to fix this error is to add an if statement to test the second number, as shown in program below.
Before introducing exception handling, let us rewrite program above to compute a quotient using a method, as shown in program below.
Enter two integers: 5 3
5 / 3 is 1
Enter two integers: 5 0
Divisor cannot be zero
The method quotient (lines 5–12) returns the quotient of two integers. If number2 is 0, it cannot return a value, so the program is terminated in line 8. This is clearly a problem. You should not let the method terminate the program—the caller should decide whether to terminate the program.
How can a method notify its caller an exception has occurred? Java enables a method to throw an exception that can be caught and handled by the caller. The preceding program can be rewritten, as shown in program below.
Enter two integers: 5 3
5 / 3 is 1
Execution continues ...
Enter two integers: 5 0
Exception: an integer cannot be divided by zero
Execution continues ...
If number2 is 0, the method throws an exception (line 7) by executing
throw new ArithmeticException("Divisor cannot be zero");
The value thrown, in this case new ArithmeticException("Divisor cannot be zero"), is called an exception. The execution of a throw statement is called throwing an exception. The exception is an object created from an exception class. In this case, the exception class is java.lang.ArithmeticException. The constructor ArithmeticException(str) is invoked to construct an exception object, where str is a message that describes the exception.
When an exception is thrown, the normal execution flow is interrupted. As the name suggests, to “throw an exception” is to pass the exception from one place to another. The statement for invoking the method is contained in a try block and a catch block. The try block (lines 19–23) contains the code that is executed in normal circumstances. The exception is caught by the catch block. The code in the catch block is executed to handle the exception. Afterward, the statement (line 29) after the catch block is executed.
The throw statement is analogous to a method call, but instead of calling a method, it calls a catch block. In this sense, a catch block is like a method definition with a parameter that matches the type of the value being thrown. Unlike a method, however, after the catch block is executed, the program control does not return to the throw statement; instead, it executes the next statement after the catch block.
The identifier ex in the catch–block header
catch (ArithmeticException ex)
acts very much like a parameter in a method. Thus, this parameter is referred to as a catch–block parameter. The type (e.g., ArithmeticException) preceding ex specifies what kind of exception the catch block can catch. Once the exception is caught, you can access the thrown value from this parameter in the body of a catch block.
In summary, a template for a try-throw-catch block may look like this:
try {
Code to run;
A statement or a method that may throw an exception;
More code to run;
}
catch (type ex) {
Code to process the exception;
}
An exception may be thrown directly by using a throw statement in a try block, or by invoking a method that may throw an exception.
The main method invokes quotient (line 20). If the quotient method executes normally, it returns a value to the caller. If the quotient method encounters an exception, it throws the exception back to its caller. The caller’s catch block handles the exception.
Now you can see the advantage of using exception handling: It enables a method to throw an exception to its caller, enabling the caller to handle the exception. Without this capability, the called method itself must handle the exception or terminate the program. Often the called method does not know what to do in case of error. This is typically the case for the library methods. The library method can detect the error, but only the caller knows what needs to be done when an error occurs. The key benefit of exception handling is separating the detection of an error (done in a called method) from the handling of an error (done in the calling method).
Many library methods throw exceptions. The program below gives an example that handles an InputMismatchException when reading an input.
Enter an integer: 3.5
Try again. (Incorrect input: an integer is required)
Enter an integer: 4
The number entered is 4
When executing input.nextInt() (line 13), an InputMismatchException occurs if the input entered is not an integer. Suppose 3.5 is entered. An InputMismatchException occurs and the control is transferred to the catch block. The statements in the catch block are now executed. The statement input.nextLine() in line 22 discards the current input line so that the user can enter a new line of input. The variable continueInput controls the loop. Its initial value is true (line 8), and it is changed to false (line 18) when a valid input is received. Once a valid input is received, there is no need to continue the input.
Posted on June 14, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.