Previous | Next | Trail Map | Writing Java Programs | Handling Errors using Exceptions


Your First Encounter with Java Exceptions

This error message
InputFile.java:8: Warning: Exception java.io.FileNotFoundException must be caught, or it must be declared in throws clause of this method.
	fis = new FileInputStream(filename);
	      ^
is one of two similar error messages you will see if you try to compile this class, InputFile, because the InputFile class contains calls to methods that will throw exceptions when an error occurs. The Java language requires that methods either catch or declare all non-runtime exceptions that can be thrown within the scope of that method (details about what this actually means are covered on the next page, Java's Catch or Declare Requirement). If the compiler detects a method, such as those in InputFile, that don't meet this requirement, it issues an error message like the one shown above and refuses to compile the program.

Let's look at InputFile in more detail and see what's going on.

The InputFile class wraps a FileInputStream and provides a method, getLine(), for reading a line from the current position in the input stream.

import java.io.*;

class InputFile {

    FileInputStream fis;

    InputFile(String filename) {
        fis = new FileInputStream(filename);
    }

    String getLine() {
        int c;
        StringBuffer buf = new StringBuffer();

        while ((c = fis.read()) != -1) {
            if (c == '\n') {
                return buf.toString();
            } else
                buf.append((char)c);
        }
        return null;
    }
}
The compiler prints the first error message because of the bold line in the above code listing. The bold line creates a new FileInputStream object and uses it to open a file (whose name is passed into the FileInputStream constructor).

So, what should the FileInputStream do if the named file does not exist on the filesystem? Well, that depends on what the program using the FileInputStream wants to do. The implementers of FileInputStream have no idea what the InputFile class wants to do if the file does not exist. Should the FileInputStream kill the program? Should it try an alternate filename? Should it just create a file of the indicated name? There's no possible way the FileInputStream implementers could choose a solution that would suit every user of FileInputStream. So, they punted, or rather, threw, an exception. That is, if the file named in the argument to the FileInputStream constructor does not exist on the filesystem, the constructor throws a java.io.FileNotFoundException. By throwing an exception, FileInputStream allows the calling method to handle the error in whatever way is most appropriate for it.

As you can see from the code, the InputFile class completely ignores the fact that the FileInputStream constructor can throw an exception. However, as stated previously, the Java language requires that methods either catch or declare all non-runtime exceptions that can be thrown within the scope of that method. Because the InputFile class does neither, the compiler prints an error message to that effect when it encounters the call to the FileInputStream constructor and refuses to compile the class.

In addition to the first error message shown above, you will also see this similar error message when you compile the InputFile class:

InputFile.java:15: Warning: Exception java.io.IOException must be caught, or it must be declared in throws clause of this method.
	while ((c = fis.read()) != -1) {
	                    ^
The InputFile class's getLine() method reads from the FileInputStream that was opened in InputFile's constructor. The FileInputStream read() method throws a java.io.IOException if for some reason it can't read from the file. Again, the InputFile class makes no attempt to catch or declare this exception. Thus you see the second error message.

At this point, you have two options, you can either arrange to catch the exceptions within the appropriate methods in the InputFile class, or the InputFile methods can "duck" and allow another method further up the call stack to catch them. Either way, the InputFile methods must do something, either catch or declare the exceptions, before the InputFile class can be compiled.

The next page describes in further detail Java's Catch or Declare Requirement. The subsequent pages show you how to comply to the requirement.


Previous | Next | Trail Map | Writing Java Programs | Handling Errors using Exceptions