Trail: Essential Java Classes
|
Lesson: Handling Errors with Exceptions
|
|
Runtime Exceptions--The Controversy
Because the Java language does not require methods to catch or specify
runtime exceptions, it's tempting for programmers to
write code that throws only runtime exceptions or to
make all of their exception subclasses inherit from RuntimeException.
Both of these programming shortcuts allow programmers to write Java
code without bothering with all of the nagging
errors from the compiler and without bothering to specify or catch
any exceptions. While this may seem convenient to the programmer, it
sidesteps the intent of Java's catch or specify requirement and can
cause problems for the programmers using your classes.
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);
^
Why did the Java designers decide to force a method to specify all uncaught
checked exceptions that can be thrown within its scope?
Because any exception that can be thrown by a method is really part of
the method's public programming interface: callers of a method must know
about the exceptions that a method can throw in order to intelligently
and conciously decide what to do about those exceptions.
The exceptions that a method can throw are as much a part of that
method's programming interface as its parameters and return value.
Your next question might be: "Well then, if it's so good to document
a method's API including the exceptions that it can throw, why not specify
runtime exceptions, too?"
Runtime exceptions represent problems that are detected by
the runtime system. This includes arithmetic
exceptions (such as when dividing by zero), pointer exceptions (such as trying
to access an object through a null reference), and indexing exceptions (such
as attempting to access an array element through an index that is too large
or too small).
Runtime exceptions can occur anywhere in a program and in a typical
program can be very numerous. Typically, the cost of checking for runtime
exceptions exceeds the benefit of catching or specifying them. Thus the compiler
does not require that you catch or specify runtime exceptions, although you can.
Checked exceptions represent useful information about the operation
of a legally specified request that the caller may have had no control
over and that the caller needs to be informed about--for example, the
file system is now full, or the remote end has closed the connection, or
the access privileges don't allow this action.
What does it buy you if you throw a RuntimeException or create a subclass
of RuntimeException just because you don't want to deal with specifying it?
Simply, you get the ability to throw an exception without specifying that
you do so. In other words, it is a way to avoid documenting the exceptions
that a method can throw.
When is this good? Well, when is it ever good to avoid documenting a
method's behavior? The answer is "hardly ever."
Rules of Thumb:
-
A method can detect and throw a
RuntimeException
when it's encountered an error in the virtual machine runtime. However, it's
typically easier to just let the virtual machine detect and throw it.
Normally, the methods you write should throw Exceptions, not RuntimeException.
-
Similarly, you create a subclass of
RuntimeException when
you are creating an error in the virtual machine runtime
(which you probably aren't). Otherwise you should subclass Exception.
-
Do not throw a runtime exception or create a subclass of
RuntimeException
simply because you don't want to be bothered with specifying the exceptions
your methods can throw.
|