Exceptions: the try/catch block

In our introduction to exceptions, we showed how an exception object thrown by a method (in fact a constructor in the example) could be caught by the caller in a construction commonly called the try/catch block. In the block preceded by try, we put the code whose exceptions we want or need to trap. In the block preceded by catch, we put the code that will be executed if and only if an exception of the given type is thrown. Let's expand on this construction here. Firstly, we didn't explicitly state the following:

As an illustration of these points, consider the following code, which opens a file, reads a line from it, and parses the line. In this example, the first line of the try block can throw a FileNotFoundException and some of the later lines can throw an IOException. Additionally, there is one line that can throw a NumberFormatException. The call to line.trim() can't actually throw any of these exceptions, but it doesn't matter: we can still include it in the same try block to avoid having to make our code messy with multiple try/catch blocks. Notice how we can even put the return statement to the method inside the try/catch block. (It's important to state that this is an example of the points mentioned so far: in reality, there are other changes we'd need to make to this code, as discussed below.)

public int getNumber(File f) {
  try {
    FileInputStream fin = new FileInputStream(f);
    BufferedReader br = new BufferedReader(new InputStreamReader(fin), "ASCII");
    String line = br.readLine();
    line = line.trim();
    int number = Integer.parseInt(line);
    br.close();
    return number;
  } catch (FileNotFoundException fnf) {
    // Oh dear, error occurred opening file
    displayErrorMessage(fnf.getMessage());
  } catch (IOException ioex) {
    displayErrorMessage(ioex.getMessage());
  } catch (NumberFormatException nfe) {
    displayErrorMessage("The file contained invalid data");
  }
  return -1; // If we get here, we didn't read a
             // number from the file
}

(Note: we're not going to get bogged down in the actual calls to perform the I/O; to learn more about things such as the BufferedReader and the readLine() method, see this site's separate introduction to I/O in Java.)

Problems with this example (and how to resolve them)

Now, there are actually still some inconveniences with the above example that we'd need to resolve:

It turns out that there's also no need for us to handle FileNotFoundException and IOException separately (unless we really want to). This is because FileNotFoundException is actually an extension (subclass) of IOException. So just catching or handling IOException is enough to cover both cases.

On the next pages, we'll look at how to resolve these problems: