Exceptions: the throws declaration

It is often inconvenient for a method to have to deal with exceptions 'there and then'. For example, a utility method to read from a file would ideally notify the caller of any error rather than displaying a UI message in the middle of that method. Firstly, because from a design perspective this avoids mixing UI code and file handling code. Secondly because the caller may just 'need to know' that an error occurred. And thirdly because passing the exception out of the method where it occurs means that errors can be handled in a more central place. Otherwise, we may end up having to put separate logging/UI code in every place where an error can occur. You don't want that in a big application.

Recall that the constructor to FileInputStream was declared as follows:

public FileInputStream(File file) throws FileNotFoundException;

We can copy this syntax to declare that our own method can throw a given exception. For example:

public int readNumberFromFile(File f) throws IOException {
  ...
}

Now inside our method, we don't need to catch IOException: if one occurs, it will be 'passed up' to the caller of our method, who in turn must catch it. We can declare our method as throwing any number of different exception types. For example:

public int readNumberFromFile(File f) throws IOException, NumberFormatException {
  ...
}

When to catch and when to throw?

We'll see that part of good program design involves deciding whether to catch or throw an exception. In a nutshell, catching is appropriate when it is realistically suitable to deal with the exception 'there and then'; throwing is appropriate when it is really the caller's responsibility. But sometimes the decision can be more subtle.

Next: throwing your own exceptions and the finally block

On the next pages, we look at the following: