By handling exceptions we end up giving some meaningful message to end user rather than giving meaningless message.
Exception handling best practices and guidelines for using exceptions in java -
- Throw exceptions when the method cannot handle the exception, and more importantly, must be handled by the caller.
In Servlets - doGet() and doPost() throw ServletException or IOException in certain circumstances where the request could not be read correctly. Neither of these methods are in a position to handle the exception, but the container is (which generally results in the 404 error page in most cases).
- Bubble the exception if the method cannot handle it. This is a corollary of the above point, but applicable to methods that must catch the exception. If the caught exception cannot be handled correctly by the method, then it is preferable to bubble it.
- Throw the exception right away. If an exception scenario is encountered, then it is a good practice to throw an exception indicating the original point of failure, instead of attempting to handle the failure via error codes, until a point deemed suitable for throwing the exception. In other words, attempt to minimize mixing exception handling with error handling.
- Either log the exception or bubble it, but don't do both. Logging an exception often indicates that the exception stack has been completely unwound, indicating that no further bubbling of the exception has occurred. Hence, it is not recommended to do both at the same time, as it often leads to a frustrating experience in debugging.
- Application should not try to catch Error - Because, in most of cases recovery from an Error is almost impossible. So, application must be allowed to terminate.
Let’s say errors like OutOfMemoryError and StackOverflowError occur and are caught then JVM might not be able to free up memory for rest of application to execute, so it will be better if application don’t catch these errors and is allowed to terminate.
- Use subclasses of checked exceptions, when you except the caller to handle the exception. This results in the compiler throwing an error message if the caller does not handle the exception. Beware though, this usually results in developers "swallowing" exceptions in code.
- Throwing RuntimeException - We must avoid throwing Runtime exceptions because they generally indicate programming errors.
- Use exception class hierarchies for communicating information about exceptions across various tiers. By implementing a hierarchy, you could generalize the exception handling behavior in the caller. For example, you could use a root exception like DomainException which has several subclasses like InvalidCustomerException, InvalidProductException etc. The caveat here is that your exception hierarchy can explode very quickly if you represent each separate exceptional scenario as a separate exception.
- Avoid catching exceptions you cannot handle. Pretty obvious, but a lot of developers attempt to catch java.lang.Exception or java.lang.Throwable. Since all subclassed exceptions can be caught, the runtime behavior of the application can often be vague when "global" exception classes are caught. After all, one wouldn't want to catch OutOfMemoryError - how should one handle such an exception?
- Wrap exceptions with care. Rethrowing an exception resets the exception stack. Unless the original cause has been provided to the new exception object, it is lost forever. In order to preserve the exception stack, one will have to provide the original exception object to the new exception's constructor.
- Convert checked exceptions into unchecked ones only when required. When wrapping an exception, it is possible to wrap a checked exception and throw an unchecked one (User defined unchecked Exception). This is useful in certain cases, especially when the intention is to stop the currently executing thread. However, in other scenarios this can cause a bit of pain, for the compiler checks are not performed. Therefore, adapting a checked exception as an unchecked one is not meant to be done blindly.
- Throwable should be caught (This might be contrary to few above mentioned points, but could be useful in certain scenarios) - rollback transactions which went wrong, if any (may be database transactions) and once transactions have been successfully rolled back we must rethrow Throwable.
What we should do when we are unable to handle specific exception ?
Lets’ say we have handled NullPointerException in code and at runtime ArithmeticException is thrown, then rather than showing ArithmeticException to user we must show him some meaningful exception and must catch ArithmeticException in its superclass Exception and log it for further analyzation.
/** JavaMadeSoEasy.com */