What are best practices for throwing exceptions?
A programmer must not be forced by an API to catch an exception to get information about the state of the service s/he is using. S/he should never use exceptions to do clever tricks.
Joshua Bloch states it like this:
[E]xceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary flow control. [...] A well-designed API must not force it clients to use exceptions for ordinary flow control.Effective Java, p. 242
For example the Iterator provides a method hasNext() to check if there are further elements to iterate over. There is no need to check for the NoSuchElementException when calling next().
There are some basic exceptions that are often used, especially for precondition checks. This table is based on Effective Java, p. 249
Exception | Occasion to Use |
---|---|
IllegalArgumentException | This is the classical precondition check to validate non-null input arguments. |
NullPointerException | Also a precondition check that an argument is not null. It is also used if a method returns a null value which is not expected. |
IllegalStateException | The state of the object is invalid prior to the invocation of a method. This problem may either be temporary or final without a cure. |
IndexOutOfBoundsException | An index parameter is out of the acceptable range. |
Throwing an exception should keep the object in the state it was prior to the method call. This is not an issue for errors.
This is archived by the following
Make sure to not throw an exception in the finally block. If you throw an exception in the finally block, the caught exception gets lost.
The stack trace provides valuable information about where a problem is located. When re-throwing an exception make sure to preserve this stack trace by exception changing unless you have proper reason to use exception translation.
If the exception you want to throw does not allow to add an exception as cause, use tip Exception with no Cause.