Exceptions: when to catch and when to throw?
Adding a throws declaration to a method allows us to
'pass the buck' and make the caller to our method deal with the exception.
Part of good program design in Java involves deciding when it is appropriate to
catch and deal with exceptions directly, and when it's more appropriate to throw them
back to the caller. The questions are often: can my method sensibly take appropriate
action, or does that action need to be taken by the caller? And: does the caller need to
know that an exception occurred?
Don't turn an exception into a return value
A good indication that you're catching the exception in the wrong place
is if you end up writing code like this:
public int readNumberFromFile(File f) {
try {
...
} catch (IOException ioex) {
return -1;
}
}
This is bad for all the reasons that error handling in C was bad: you put the onus
on the caller to remember to check for the error value; you remove the possibility of
using that particular value as a genuine "value" (i.e. our file now can't contain
the number -1); you make it clumsy for the caller to find out information
about the error; and if the caller in turn can't handle the error immediately,
then they have to resort to some similar tactic for notifying their caller
(and at that point, for the caller of the caller to find out more details about the
error is going to involve some particularly klutzy program flow).
Don't swallow exceptions
Another favourite among some programmers appears to be to "swallow" an exception
and make the program carry on regardless, as though "nothing happened":
private String line = null;
public void populateLine(BufferedReader br) {
try {
this.line = br.readLine();
} catch (IOException ioex) {
// maybe log the error in some unuseful place but
// whatever we do don't let the caller know there
// was a problem...
}
}
A caller to populateLine() will be expecting the line variable
to be populated with a line from the file. If this isn't possible, the above
method simply pretends that nothing happened. Later on in time, some part of the
program will try to access the line method, and you'll probably end up
with a spurious NullPointerException whose cause will be more difficult
to track down.
So in general: if an exception occurs, there's usually no benefit in
pretending it didn't. If your method can't deal with it, that's usually a
good sign that you need to throw it up to the caller.
So when to catch...?
In case you think we've painted a negative picture of catching exceptions, there are
of course cases where it is appropriate to catch the exception. (After all, it has
to be caught somewhere eventually...) Typically, exceptions are caught in
places where:
- you're in some kind of "central" error-handling place;
- in GUI event handlers, thread run() methods or other places
where there's "nowhere else to pass the exception on to";
- where there's no need for the exception to interrupt the logic of your
prorgam flow.
An example of the last case would be a routine that took lines of input from a file,
but knew that occasionally a line would be malformed. The routine might want to
ignore the malformed lines (although presumably still log them in some way) and still
process the good ones, rather than rejecting 100,000 lines of data because of 3 malformed items.
There are also a few cases where we're forced to deal with an exception (because Java
makes us) in cases where we really don't expect the exception to occur. For example,
we really wouldn't expect a ClassNotFoundException to occur while deserialising
a String, but Java forces us to worry about handling such a case.
If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.
Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.