injection ) to provide the programmer with singletons automatically, rather than via
an explicit Singleton (or equivalent) class.
Exceptions and Exception Handling
We met checked and unchecked exceptions in “Checked and Unchecked Excep‐
tions” on page 70 . In this section, we discuss some additional aspects of the design
of exceptions, and how to use them in your own code.
Recall that an exception in Java is an object. The type of this object is
java.lang.Throwable , or more commonly, some subclass of Throwable that more
specifically describes the type of exception that occurred. Throwable has two stan‐
dard subclasses: java.lang.Error and java.lang.Exception . Exceptions that are
subclasses of Error generally indicate unrecoverable problems: the virtual machine
has run out of memory, or a class file is corrupted and cannot be read, for example.
Exceptions of this sort can be caught and handled, but it is rare to do so—these are
the unchecked exceptions previously mentioned.
Exceptions that are subclasses of Exception , on the other hand, indicate less severe
conditions. These exceptions can be reasonably caught and handled. They include
such exceptions as java.io.EOFException , which signals the end of a file, and
java.lang.ArrayIndexOutOfBoundsException , which indicates that a program has
tried to read past the end of an array. These are the checked exceptions from Chap‐
ter 2 (except for subclasses of RuntimeException , which are also a form of
unchecked exception). In this topic, we use the term “exception” to refer to any
exception object, regardless of whether the type of that exception is Exception or
Because an exception is an object, it can contain data, and its class can define meth‐
ods that operate on that data. The Throwable class and all its subclasses include a
String field that stores a human-readable error message that describes the excep‐
tional condition. It's set when the exception object is created and can be read from
the exception with the getMessage() method. Most exceptions contain only this
single message, but a few add other data. The java.io.InterruptedIOException ,
for example, adds a field named bytesTransferred that specifies how much input
or output was completed before the exceptional condition interrupted it.
When designing your own exceptions, you should consider what other additional
modeling information is relevant to the exception object. This is usually situation-
specific information about the aborted operation, and the exceptional circumstance
that was encountered (as we saw with java.io.InterruptedIOException ).
There are some trade-offs in the use of exceptions in application design. Using
checked exceptions means that the compiler can enforce the handling (or propaga‐
tion up the call stack) of known conditions that have the potential of recovery or
retry. It also means that it's more difficult to forget to actually handle errors—thus
reducing the risk that a forgotten error condition causes a system to fail in