An exception indicates a problem that occurs during a program’s execution. With exception handling, a program can continue executing (rather than terminating) after dealing with a problem. For example, robust and fault-tolerant programs should be able to deal with problems as they arise and continue executing.
Exceptions are thrown when a method detects a problem and is unable to handle it. When an exception occurs and is not handled, a stack trace is displayed, including the name of the exception, a (hopefully) descriptive message, and the series of method calls that led to the exception. This information helps you locate where the exception occurred so you can debug the program.
Java contains a class hierarchy of pre-defined exceptions and errors. See many on-line resources such as here and here for more information. Java distinguishes two types of exceptions: checked and unchecked exceptions.
There has been debates on whether it is more desirable to use checked or unchecked exceptions. Using checked exceptions, programmers have to declare exceptions that each method may throw and tend to provide more detailed documentation of the behavior of the program. However, when not used correctly, checked exceptions can lead to some programming problems and difficulties, especially for large projects. Using unchecked exception, programmers do not declare any specific exceptions, but may still throw exceptions. This can lead to problems and difficulties for users of the classes and methods, due to the lack of information about program behaviors. See here for some discussions and guidelines on these topics.
All the example programs mentioned below are in chapter11.zip.
In the DivideByZeroNoExceptionHandling program, the user is supposed to enter two integers, then the program performs a division and prints the result. One possibility is an ArithmeticException if the user enters a 0 for the denominator. Another possibility is an InputMismatchException if the user does not enter an integer (or enters an integer too large to be an int).
The DivideByZeroWithExceptionHandling program illustrates how to handle these problems using a try-catch statement (also called try-catch-finally). This statement consists of one try block, one or more catch blocks, and an optional finally block. The idea is that if an exception is thrown when running the code in the try block, then the code in an appropriate catch block should recover from the error. The finally block is useful if there is some resource that needs postprocessing no matter what, e.g., closing a file.
The DivideByZeroWithExceptionHandling program has a loop that keeps trying to get valid input from the user. The try-catch within the loop has a try block that obtains two ints from the user, performs a division, and sets a flag so the loop will end. However, if the user does not enter ints, an InputMismatchException will occur; this is handled by the first catch block. If the user enters 0 for the denominator, an ArithmeticException will occur; this is handled by the second catch block.
It is important to remember that when an exception occurs within a try block, the rest of the code in the try block will be skipped over. Instead, control is transferred to the catch block. So, the only way the value of the flag will be changed in DivideByZeroWithExceptionHandling is if the try block runs to completion without any exceptions.
The UsingExceptions1, UsingExceptions2 and UsingChainedExceptions programs illustrate other aspects of exception handling in Java. Finally blocks were already mentioned earlier.
If your code detects an anomaly that can only be fixed by the caller of the method, then your code should have a throw statement to throw an exception. Look through the Exception hierarchy to see if one of the subclasses is appropriate for you, or create a new class that extends Exception.
A throws clause is needed if an exception can occur in a method, but the method does not handle it (see the UsingExceptions2 program). A throws clause tells Java that the method caller needs to handle the exception (or has a throws clause to pass the responsibility to its caller).
The UsingException2 program also illustrates some of the information that can be accessed from an exception.
The AssertTest program shows how to use an assertion in a Java program to check if an input is within a given range. To run this program, you might need to enable assertions in the JRE with the -ea option. In Eclipse, you can click Run->Run Configuration->Arguments and enter -ea as the VM arguments. Then click the run button.