Principle
-
Exceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary control flow.
// Horrible abuse of exceptions. Don't ever do this!
try {
int i = 0;
while(true)
range[i++].climb();
} catch(ArrayIndexOutOfBoundsException e) {
}
-
A well-designed API must not force its clients to use exceptions for ordinary control flow.
for (Iterator<Foo> i = collection.iterator(); i.hasNext(); ) {
Foo foo = i.next();
...
}
If Iterator lacked the hasNext method, clients would be forced to do this instead:
// Do not use this hideous code for iteration over a collection!
try {
Iterator<Foo> i = collection.iterator();
while(true) {
Foo foo = i.next();
...
}
} catch (NoSuchElementException e) {
}
- An alternative to providing a separate state-testing method is to have the state dependent method return a distinguished value such as null if it is invoked with the object in an inappropriate state. This technique would not be appropriate for Iterator, as null is a legitimate return value for the next method.
- Guidelines to choose between a state-testing method and a distinguished return value.
Different concerns |
State-testing method |
Distinguished value |
Concurrent Object Accessing without external synchronization/externally induced state transitions |
N |
Y |
Performance concerns |
N |
Y |
Other situations except the conditions above |
Y |
N |
Readability |
Y |
N |
Incorrect use detectable |
Y |
N |
Summary
Exceptions are designed for use in exceptional conditions. Don't use them for ordinary control flow, and don't write APIs that force others to do so.