|
|
|
Sponsored Link •
|
|
Advertisement
|
What to throw?
Once you have decided to throw an exception, you need to decide which
exception to throw. You can throw an instance of class
Throwable, or any subclass of Throwable. You
can throw an already existing throwable object from the Java API, or
define and throw one of your own. How do you decide?
Exceptions versus errors
In general, you should throw an exception and and never throw errors.
Error, a subclass of Throwable, is intended
for drastic problems, such as OutOfMemoryError, which
would be reported by the JVM itself. On occasion an error, such as
java.awt.AWTError, could be thrown by the Java API. In
your code, however, you should restrict yourself to throwing exceptions
(subclasses of class Exception). Leave the errors to the
big guys.
Checked vs Unchecked exceptions
The big question, then, is whether to throw a "checked" or an
"unchecked" exception. A checked exception is some subclass of
Exception (or Exception itself), excluding
class RuntimeException and its subclasses. Unchecked
exceptions are RuntimeException and any of its
subclasses. Class Error and its subclasses also are
unchecked, but as you should be focusing on throwing exceptions only,
your decision should be whether to throw a subclass of
RuntimeException (an unchecked exception) or some other
subclass of Exception (a checked exception).
If you throw a checked exception (and don't catch it), you will need to
declare the exception in your method's throws clause.
Client programmers who wish to call your method will then need to
either catch and handle the exception within the body of their methods,
or declare the exception in the throws clause of their methods. Making
an exception checked forces client programmers to deal with the
possibility that the exception will be thrown.
If you throw an unchecked exception, client programmers can decide whether to catch or disregard the exception, just as with checked exceptions. With an unchecked exception, however, the compiler doesn't force client programmers either to catch the exception or declare it in a throws clause. In fact, client programmers may not even know that the exception could be thrown. Either way, client programmers are less likely to think about what they should do in the event of an unchecked exception than they are in the case of an checked exception.
The simple guideline is:
If you are throwing an exception for an abnormal condition that you feel client programmers should consciously decide how to handle, throw a checked exception.
In general, exceptions that indicate an improper use of a class should be unchecked. The StringIndexOutOfBoundsException thrown by
String's charAt() method is an unchecked
exception. The designers of the String class didn't want
to force client programmers to deal with the possibility of an invalid
index parameter every time they called charAt(int
index).
The read() method of class
java.io.FileInputStream, on the other hand, throws
IOException, which is a checked exception. This exception
indicates some kind of error occurred while attempting to read from the
file. It doesn't indicate that the client has used the
FileInputStream class improperly. It just signals that
the method itself is unable to fulfill its contractual responsibility
of reading in the next byte from the file. The designers of the
FileInputStream class considered this abnormal condition
to be common enough, and important enough, to force client programmers
to deal with it.
That is the trick, then, of deciding between a checked and an unchecked exception. If the abnormal condition is a failure of the method to fulfill its contract, and you feel it is common or important enough that client programmers should be forced to deal with the possibility of the exception, throw a checked exception. Otherwise, throw an unchecked exception.
Define a specific exception class
Finally, you must decide which exception class to instantiate
and throw. The general rule here is to be specific. Don't just
throw Exception, for example, with a string message
indicating the kind of abnormal condition that caused the exception.
Define or choose an already existing exception class for each kind of
abnormal condition that may cause your method to throw an exception.
This way, client programmers can define a separate catch clause for
each kind of exception, or can catch some but not others, without
having to query the object to determine the kind of abnormal condition
that caused the exception.
You may wish to embed some information in the exception object, to give the catch clause more details about the exception. But you don't want to rely solely on embedded information to distinguish one type of exception from another. You don't want clients to have to query the exception object to determine, for example, whether the problem was an I/O error or an illegal argument.
Note that when String.charAt(int index) receives a bad
input, it doesn't throw RuntimeException or even
IllegalArgumentException. It throws
StringIndexOutOfBoundsException. The type name indicates
that the problem was a string index, and the program can query the
object to find out what the bad index was.
|
Sponsored Links
|