Exception Handling Mechanisms in Java
The exception handling mechanisms in Java provide a clean way to check for errors without cluttering code. Exceptions also provide a means to signal errors directly rather than use flags or side effects such as fields that must be checked. Exceptions make the error conditions that a method can signal an explicit part of the methods contract. The list of exceptions can be seen by the programmer, checked by the compiler and preserved by extended classes that override the method.
Traditional error handling methods include Boolean functions (which return TRUE/FALSE), integer functions (returns –1 on error) and other return arguments and special values [1] . Some of the drawbacks associated with these methods are that the programmer must remember to check for the return codes, it can lead to diminished readability of the source code, and one cannot rely on the functions being consistent [2].
In Java, an exception is thrown when an unexpected error condition is encountered. The exception is then caught by an encompassing clause further up the method stack. If the exception is not caught, a default exception handler takes effect, usually printing useful information about where the exception was thrown (such as a call stack). However, this method of handling exceptions is not a silver bullet.
Exceptions in Java are objects. All exception types must extend the Java language class Throwable or one of its subclasses. By convention, new exception types extend Exception, a subclass of Throwable. Java exceptions are primarily checked exceptions i.e. the compiler verifies that methods throw only exceptions that they have declared.
Java also avoids some of the problems with the exception handling mechanisms of C++, by providing a finally clause. In C++, when an exception leaves the scope of a function, all objects which are allocated on the stack are reclaimed, and their destructors are called. Thus, if you want to free a resource or otherwise clean something up when an exception passes by, you must put that code in the destructor of an object. This is artificial, error prone, and inconvenient [4]. Every scope in Java can have a 'finally' clause. Any time a scope is exited, regardless of the reason for that exit (e.g. the function could simply return, or an exception could pass through it) the code in the finally clause is executed. Thus, cleanup code does not have to be artificially put into some destructor. This makes Java exceptions much easier to use than C++ exceptions.
Exceptions are thrown using a throw statement, which takes an object as a parameter [5]. An exception can also be generated by invoking a method that itself throws an exception. The throws clause takes a comma separated list of exception types. The contract defined by the throws clause is strictly enforced i.e. one can only throw an exception that has been declared in the throws clause. This helps avoid bugs that result from not handling errors since this states which exceptions are being thrown by methods and makes sure they are dealt with in some way by the invoker.
Exceptions are caught by enclosing code in try blocks [5]. The body of the try statement is executed until either an exception is thrown or it finishes successfully. If an exception is thrown, each catch clause is examined in turn from first to last to see whether the type of the exception object is assignable to the type declared in catch. Any number of catch clauses can be associated with a particular try as long as each clause catches a different type of exception.
If a finally clause is present in a try, its code is executed after all the processing in the try is complete [5]. This happens regardless of how the completion was achieved i.e. normally, through an exception or through a control flow statement like return or break.
A significant deficiency in Java’s exception handling mechanism is the absence of Design by Contract. One of the goals of this project is to examine its impact on Java, describe how Design By Contract can be used to complement Java’s exception mechanism and provide an overview of the various techniques of implementing Design by Contract in Java.
References