Exception Handling


A program may not always reach to its end. It might be interrupted in several ways. A logical error in your program could crash it. For example, you might be trying to access an element of an array beyond its length. The misbehaved user could enter a String when asked for an int and lastly, the computer itself could go out of memory requiring the program to end. Some of them cannot be handled but the others can. For example, if a user enters a String when an int is needed, the program would terminate abruptly printing an error message. We can override this default behaviour so that the program asks for a proper input a second time. This is attained using Java’s exception handling statements.

An Exception in Java is an object which contains information about the error that has occurred. These Exception objects are automatically created when an unexpected situation arises. If we do not provide any exception handlers, as already told, an error message is printed. Before we learn how to provide our own exception handlers, let us see what the default handler provided by the compiler does. For this purpose, let us write a program which takes an int as an input from the keyboard. Simulating a misbehaved user, let us enter a String instead of an int. Here is the program for this purpose.

import java.util.Scanner;
public class TakeInput {

    public static void main(String[] args){
     Scanner s=new Scanner(System.in);
     System.out.print(“Enter an integer: “);
     int num=s.nextInt();
     System.out.println(“You entered “+num);
    }

And here is a sample output when we enter the String “Java” when we were supposed to enter an integer.

Enter an integer: Java
Exception in thread “main” java.util.InputMismatchException
 at java.util.Scanner.throwFor(Scanner.java:840)
 at java.util.Scanner.next(Scanner.java:1461)
 at java.util.Scanner.nextInt(Scanner.java:2091)
 at java.util.Scanner.nextInt(Scanner.java:2050)
 at TakeInput.main(TakeInput.java:7)

As you can see in the output above, the program was terminated midway. The last statement which prints “You entered …” was not executed. The method nextInt() expects an int but what it received is a String. And so, the method nextInt() has thrown an InputMismatchException which you can see on the second line of the output. This Exception has occurred in the main thread. We shall see in a later chapter what a thread is. And the remaining lines point out to the code where this particular Exception has occurred. This is known as unwinding the stack trace.

To know what a stack trace is, let us consider the following program.

class Example {

    public static void main(String[] args) {
        a();
    }

    public void a() {
        b();
    }

    public void b() {
        c();
    }

    public void c() {
    }
}

The execution of this program starts with the main() method. From main(), the method a() is invoked. a() then invokes b() and finally b() invokes c(). After c() completes its execution, there should be a way to know as to where which the control should be tranferred, b(), a(), main() or a method in some other class? This information is held in method activation stack. A stack is a data structure (data structures store information) onto which items can be pushed or popped (removed). You can think of a stack as a pile of books. We place books on an existing stack of books only on the top and we also remove books only from the top. We don’t insert or remove books from the middle of the pile. A stack is therefore, a first in, last out data structure since the data item which is pushed onto the stack first is popped out of the stack at the end. A record of method calls is held in such a stack. When a method is pushed onto a stack, the line number of the other method to where it should return and the argument variables of the current method are also pushed onto it. This is why the scope of the argument variables end when the method completes execution as these variables are pushed out of the stack along with the method record. So, in this program, the method main() is first pushed onto the stack followed by a(), b() and c(). If c() invokes a method of some other class, even that would be pushed onto the stack. Once c() completes execution, it is popped out of the stack and control passes to the method b(). Next b() is popped out in a similar way followed by a(). In this way, the virtual machine executing the program is capable of knowing where to return back.

Now, we move back to the sample output of the TakeInput class. Look at the lines in the output. The method stack has been unwound. The line numbers on which the error occurred are also printed. We haven’t explicitly invoked any method by name forNext() or next(). These were invoked from within the nextInt() method which we have called. Hence, they too are printed in the stack trace. The line numbers are also displayed which would help us in finding the source of error.

However, a user using this program might get confused on seeing such lines of code. An alternative way to program would be to display a message that he has entered an invalid value and stop the program rather than allowing the above messages to be printed. We do it by using try catch finally blocks. A try block encloses the code which may throw Exceptions. You can find out if a particular method throws an Exception by looking at the documentation of the class. Along with the method names and descriptions, the exceptions that it may throw are also listed. The catch blocks provide a means to handle these Exceptions. A try block may be followed by any number of catch blocks. Each catch blocks handles a particular type of Exception. As we have already said, an Exception is an object. The corresponding catch block receives the Exception thrown by the try block into a variable specified in eth catch clause and processes the Exception. And lastly comes the finally block which contains code that will be executed whether or not an Exception has occurred.

try {
    // code
} catch ( <Exception type > < identifier > ) {
    // code
} // more catch blocks
finally {
}

If no Exceptions are thrown by the try block, none of the catch blocks are executed. Control passes directly to the finally block. However, if an Exception is thrown by the try block, then the remainder of the code in try block is skipped and the type (class type) of the Exception is compared with each of the catch blocks in the same order in which they are defined until a match if found. When an appropriate match is found, the corresponding catch block is executed and the remaining catch blocks are skipped. And then the finally block is executed. A try block should be followed by atleast one catch or finally block. One important thing that should be remembered is that variables defined in any of the try, catch of finally blocks have their scope and lifetime limited to that block itself.

The following program shows a modified version of the TakeInput program where the statements are enclosed within the try block. The Exception that might be thrown here is a InputMismatchException and hence a catch block has been provided to handle it. Look at the code within the parentheses following the catch keyword. The Exception type has been declared followed by an identifier in which the thrown Exception object would be received just like the way a method receives arguments in its parameters. We will see later on how we can use this Exception object to display the error that has occurred and also print the stack trace. For now, the type is provided only to target the catch block to be executed for that Exception. We have no intention to use the object to retrieve details of the Exception that has occurred.

import java.util.Scanner;
import java.util.InputMismatchException;
public class TakeInput {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        try {
            System.out.print(“Enter an integer: “);
            int num = s.nextInt();
            System.out.println(“You entered ” + num);
        } catch (InputMismatchException e) {
            System.out.println(“You have entered invalid data”);
        }
    }
}

Note that the import declaration has been modified to import InputMismatchException as well since we have used that class type in our catch statement. If you prefer to do so, you might import the entire package as well. We have provided only a catch block and no finally block. Run the above program and see the output. When you enter a valid integer, the program works normally.

Enter an integer: 34
You entered 34

In the other case, the statement which displays the accepted integer is skipped in the try block and the string “You have entered invalid data” is printed.

Enter an integer: Java
You have entered invalid data

Modify the above code and include a finally block also, in addition to the try and catch blocks.

// try and catch blocks
finally {
    System.out.println(“Finally is always executed”);
}

Run the program, first providing an int as the input value and then providing a String or a float (anything other than an int). You will notice that the finally block is always executed. Now modify the program to remove the catch block. Our program now contains only a try and a finally block. Execute the program. When you give an integer as the input, the output appears fine. Now, when you give an invalid input, a part of the try block is executed followed by the finally block. In addition, the stack trace is also printed similar to what we have seen when no Exception handling was provided. The reason is that even though we have provided Exception handling statements, we haven’t caught the exception. If a try catch finally sequence doesn’t catch an exception, the exception is rethrown. If these set of try catch finally statements are enclosed within another set of try catch finally blocks, control moves to the catch blocks of that set. Since, in this case, there were no nested blocks; the exception was handled by the default exception handler. You will notice a similar output if you provide catch blocks that cannot handle the InputMismatchException. For instance, provide a catch block for ArithmeticException. This is thrown in certain situations like dividing an integer with zero, finding the square root of a number. This exception is a part of java.lang package. Hence, we need not import it. You will notice that the output still remains the same. This is because, InputMismatchException was still not handled.

// try
catch ( ArithmeticException e ) {
    System.out.println(“ArithmeticException handled”);
}
// finally

Now modify the code again and replace the ArithmeticException with Exception. This is the superclass of all Exception types.

//try
catch ( Exception e ) {
    System.out.println(“Exception handled”);
}
//finally

When you provide a String as an input, you will see in the output that this particular catch block was executed. This is because an InputMismatchException is an Exception ( ‘is a ‘ relationship as InputMismatchException is a subclass of Exception) In other words, a particular catch block is executed if on operating the thrown object with the instanceof operator and the type stated in the catch clause returns true. This means that we can also specify an interface as a type. However, there is an Exception as to what type can be specified. Only classes that implement the Throwable interface can be specified in the catch clause. Define a catch clause with a String type and you will receive compilation errors. The Throwable interface is an empty interface. It doesn’t contain any methods to be implement. It is a implemented by a class to simply state that one can catch or throw objects of that type and the object represents an Exception.

Now, lastly modify the code to include only the try block with no catch or finally blocks. You will receive compilation errors as a try block needs to be followed by atleast a single catch or a finally block.

The following example shows how exception handling can be used along with loops to repeatedly ask the user to enter some data until he enters the required type. In this example, the program asks for an integer. If the user enters some other data of some other type, a message is displayed and the programs asks for new input.

public class TakeInput {

    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        boolean success = false;
        while (!success) {
            try {
                System.out.print(“Enter an integer: “);
                int num = s.nextInt();
                System.out.println(“You entered ” + num);
                success = true;
            } catch (InputMismatchException e) {
                s.next();
                System.out.println(“You have entered invalid data”);
            }
        }
    }
}

Note that within the catch block, we have included the statement, s.next(). This is because the input stream still contains an invalid data ( date other than int ). To ignore this data, we read it as a word. If the user has entered multiple words, each of these words would be ignored in the subsequent iterations. Here is a sample execution.

Enter an integer: java
You have entered invalid data
Enter an integer: 34793479347934793479
You have entered invalid data
Enter an integer: java programming
You have entered invalid data
Enter an integer: You have entered invalid data
Enter an integer: 347
You entered 347

Next : Exception hierarchy
Prev : Abstract classes and methods

Author: , 0000-00-00