Trail: Essential Java Classes
|
Lesson: Handling Errors with Exceptions
|
|
Your First Encounter with Java Exceptions
The following error message
is one of two similar error messages you will see if you try to compile
the class InputFile,
because the InputFile class contains calls to methods
that throw exceptions when an error occurs:
InputFile.java:8: Warning: Exception java.io.FileNotFoundException must be caught, or it must be declared in throws clause of this method.
in = new FileReader(filename);
^
The Java language requires that methods either catch or
specify all checked exceptions that can be thrown within the scope
of that method. (Details about what this actually means are covered in the next section,
Java's Catch or Specify Requirement.) If
the compiler detects a method, such as those in InputFile, that doesn'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 FileReader and provides a method,
getWord, for reading a word from the current position in
the reader.
// Note: This class won't compile by design!
import java.io.*;
public class InputFile {
private FileReader in;
public InputFile(String filename) {
in = new FileReader(filename);
}
public String getWord() {
int c;
StringBuffer buf = new StringBuffer();
do {
c = in.read();
if (Character.isWhitespace((char)c))
return buf.toString();
else
buf.append((char)c);
} while (c != -1);
return buf.toString();
}
}
The compiler prints the first error message because of the bold line in the above
code listing. The bold line creates a new FileReader object and uses it to open
a file whose name is passed into the FileReader constructor.
So what should the FileReader do if the named file does not exist on
the file system? Well, that depends on what the program using the FileReader wants
to do.
The implementers of FileReader have no idea what the InputFile class wants
to do if the file does not exist. Should the FileReader 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 FileReader implementers could choose a
solution that would suit every user of FileReader. So, they punted, or rather,
threw, an exception. If the file named in the argument to the FileReader
constructor does not exist on the file system, the constructor throws a
java.io.FileNotFoundException. By throwing an exception, FileReader 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 FileReader constructor can throw an exception.
However, as stated previously, the Java language requires that a method either catch or
specify all checked exceptions that can be thrown within the scope
of that method.
Because the InputFile class does neither, the compiler refuses to compile the program
and prints an error message.
In addition to the first error message shown above, you also see the following 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 = in.read()) != -1) {
^
The InputFile class's getWord method reads from the FileReader
that was opened in InputFile's constructor. The FileReader 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 specify 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 other methods further up the call stack to catch them. Either way, the
InputFile methods must do something, either catch or specify the exceptions, before
the InputFile class can be compiled. For the diligent, there's a class,
InputFileDeclared, that fixes the
bugs in InputFile by specifying the exceptions.
The next section describes in further detail Java's
Catch or Specify Requirement. The subsequent sections show you how to comply to
the requirement.
|