Exception Handling in Java: Asynchronous Exceptions and Important guidelines
Asynchronous Exceptions
The exceptions we have seen so far are synchronous in nature, in the sense that we know the point in the program where they occur and when they happen, and we process them immediately in the same thread. Contrary to this, an asynchronous exception may occur at any point in the execution of a program.
For example, an internal error generated by the JVM is a type of asynchronous exception—we don’t know when it will occur. Similarly, when we execute a stop method of the Thread or ThreadGroup class we cause an asynchronous exception in another thread. Handling such exceptions is nontrivial and sometimes impossible to handle.
Guidelines for Using Exceptions
We’ll look at some guidelines on how to use exception handling efficiently in your program code. Use exception handling judiciously. Wherever our program code can perform a simple check to avoid errors, do it rather than waiting for the exceptions to occur. In other words, do not use exception handling unless we are required to do so.
Let’s suppose we have written a stack class and have written a method, pop, that pops an element from the stack. Before we perform a pop operation on the stack, we must confirm that the stack is not empty. A simple check will reveal this condition, and doing so will be more efficient than letting an exception occur in the running code.
Another example would be checking the number of command-line arguments passed to our program. It would be more efficient to ensure that the user has indeed supplied the required number of parameters rather than letting an exception occur in the running code. In situations similar to our earlier example where an ArrayIndexOutOfBoundsException occurred, the real fix for the array access exception is not to handle the exception, but to fix the code.
Some developers put the try/catch block on every possible statement in the program code. This results in cluttering the code with several try/catch blocks and obscures the program’s main logic. Organize all the suspected statements in a single try block and provide multiple handlers to this try block. If you prefer, you may throw the exceptions to the caller and centralize all the exception processing, as discussed in previous posts.
Because Java makes it mandatory to handle all the checked exceptions, oftentimes programmers tend to provide an empty exception handler like the one shown here:
try { // do something } catch (Exception e) {} // do not do this. |
Never do this, because if an exception occurs at any time, it will be silently ignored. Ignoring an exception would result in an unpredictable program state, which would be difficult to diagnose and fix.
Another important question that comes to the programmer’s mind is, Should I handle the exception or pass it on to somebody else? Whenever possible, handle the exception. It is always better to handle the exceptions near the place where it occurs initially. If we feel that centralizing the exception handling can improve the code readability, feel free to pass the exception to the caller.
Also, it is important that we make best use of the exception hierarchy. Wherever possible, provide the handlers for the subclass exceptions rather than the most generic exception. If the existing exception class does not adequately describe the exception in your problem domain, create your own exception class.
Lastly, and most important, do not forget the golden rules:
· Be specific.
· Throw early.
· Catch late.
Allen Scott
12-Apr-2017