|
SYS-CON.TV Webcasts
Comments
Did you read today's front page stories & breaking news?
SYS-CON.TV
|
Top Links You Must Click On
General Java Exception Handling in Java
Exception Handling in Java
By: Maros Cunderlik
Sep. 1, 1997 12:00 AM
Introduction The alternative to these techniques was introduced in C++. The exception mechanism offered an elegant error handling technique that quickly became the primary tool for dealing with errors in OO languages. The concept of exception handling is based on separating error processing from the rest of the code and redirecting the flow of control to the exception block should an error occur. Given the ability to "catch", "throw" and propagate the exception, developers have a powerful tool to create robust and encapsulated components. Although Java's exception mechanism was originally derived from C++, there are several key differences that every Java programmer should be aware of. Since many Java developers usually have a strong C++ background, they tend to re-use' their C++ coding techniques in Java. While syntactically correct, this approach frequently results in hybrid and ineffective code. To better understand the underlying issues, we will take a closer look at the C++ implementation of exception handling first.
C++ Exceptions The real power of C++ exceptions is closely related to one of the most tedious tasks in C++: memory management. When an exception is thrown and the control flow is re-directed back to the caller, the call stack unwinding begins and all local objects are deleted and their destructors called. This process continues until the matching catch block is found. Otherwise, function terminate is called to abort the execution. The C++ exception mechanism, however, has its limitations. Not surprisingly, most of the problematic issues are also related to memory management. While it is true that all local objects get destroyed during stack unwinding, none of the dynamically allocated memory is reclaimed. Listing 1 shows C++ function WillLeakMemory that instantiates two objects of classes fstream and DatabaseConnection. We assume that, as with any well-behaved database class, our DatabaseConnection throws an exception if any database-related errors occur (e.g. time-out, lost or busy connection, invalid password). Given that something really goes wrong with the database connection, the exception is thrown and no dynamically created objects will get deleted. There are, of course, programming techniques that address this problem. This includes handling exceptions locally (de-allocate resources only after all possible exceptions are caught), catching exceptions locally, deleting resources and then re-throwing the exception or using a resource manager that will be allocated on the stack and will de-allocate all resources in its destructor. None of these solutions are simple, or convenient. More problems can occur when throwing an exception in the C++ constructor. The memory for the object itself has already been allocated by the time the constructor is called, which usually results in the object remaining allocated. Finally, C++ exception specifications are optional and no compile-time checking is performed. The following function declarations indicate that Fun1() can throw none or any defined exception and Fun2() does not throw any exceptions.
void Fun1(); Why would designers of the language decide to implement exception handling this way? To understand why, we must first understand the fundamental premise of C++: Provide a developer with powerful tools and assume that they know what they are doing. If you keep this in mind, you will have no difficulties using exceptions in C++ and will enjoy all the benefits and power they provide.
Java Exceptions Syntactically, Java exceptions are very similar to the C++ implementation. There is the familiar throw statement, try and catch blocks. The idea remains the same: provide a mechanism for separating the error handling routine from the rest of the code and initiate the control flow transfer whenever an error occurs. Java exception handling, however, goes far beyond the basics. Following is an explanation of the features that make Java exceptions a powerful part of the language.
Exception Hierarchy You should not attempt to catch instances of the Error class or its subclasses because they generally indicate an unrecoverable error such as LinkageError, ThreadDeath or VirtualMachineError. The Exception class is the superclass of all exceptions in the traditional C++ sense. All standard, pre-defined exception classes in Java extend the Exception class, including RuntimeException class. As its name suggests, the RuntimeException class and its subclasses are used to indicate the runtime errors such as division by zero (ArithmeticException), invalid cast (ClassCastException) or passing an illegal argument (IllegalArgumentException).
Compile-Time Checking Compile-time checking also has its disadvantages. For example, assume the programmer takes all measures to ensure that no errors will occur. Nevertheless, if any exceptions were specified in method declarations, the programmer is still forced to provide try and catch blocks. Therefore, methods should not throw exceptions just to return values or if the error can be processed locally. Doing so will result in redundancy and inefficient code.
Throw - Catch - Finally
Inheritance and Interfaces Similar rules are enforced when exceptions are specified in interfaces. If an interface specifies exceptions in its declaration, all implementations must comply to this "contract". When one class method implements more that one interface method, the overriding declaration must be compatible with all interface declarations. For example, Listing 5 will result in the compile-time error since the Impl class declaration "breaks" the interface A exception specification.
Conclusion Java's implementation of exception handling introduces several new features: Java exception hierarchy, try-catch-finally construct and compile-time checking. Java exceptions are easy to use and can be a very powerful tool. However, as with any language feature, exceptions must be used properly. Creating complicated hierarchies and declaring unnecessary exceptions can produce redundant and inefficient code. It is important to understand that no exception mechanism is perfect. If you want to have more control to make your code robust and easy to use, you will appreciate C++ exceptions. On the other hand, if you want to implicitly enforce certain design rules and are not concerned with some redundant code, you will like Java's implementation of exception handling. In any case, understanding the underlying principles of exception handling will help you design robust and effective code regardless of the language you use.
References Reader Feedback: Page 1 of 1
Enterprise Open Source Magazine Latest Stories . . .
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||