epubjs
Version:
Render ePub documents in the browser, across many devices
418 lines (414 loc) • 66.2 kB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Exceptions</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Exceptions"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-4-SECT-5"/>Exceptions</h1></div></div></div><p>Java has its roots in embedded systems—software that runs inside
specialized devices, such as handheld computers, cellular phones, and
fancy toasters. In those kinds of applications, it’s especially important
that software errors be handled robustly. Most users would agree that it’s
unacceptable for their phone to simply crash or for their toast (and
perhaps their house) to burn because their software failed. Given that we
can’t eliminate the possibility of software errors, it’s a step in the
right direction to recognize and deal with anticipated application-level
errors methodically.</p><p>Dealing with errors in some languages is entirely the responsibility
of the programmer. The language itself provides no help in identifying
error types and no tools for dealing with them easily. In the C language,
a routine generally indicates a failure by returning an “unreasonable”
value (e.g., the idiomatic <code class="literal">-1</code> or
<code class="literal">null</code>). As the programmer, you must know
what constitutes a bad result and what it means. It’s often awkward to
work around the limitations of passing error values in the normal path of
data flow.<sup>[<a id="learnjava3-CHP-4-FNOTE-3" href="#ftn.learnjava3-CHP-4-FNOTE-3" class="footnote">9</a>]</sup> An even worse problem is that certain types of errors can
legitimately occur almost anywhere, and it’s prohibitive and unreasonable
to explicitly test for them at every point in the software.</p><p>Java offers an elegant solution to these problems through
<span class="emphasis"><em>exceptions</em></span>. (Java exception handling is similar to,
but not quite the same as, exception handling in C++.) An
<span class="emphasis"><em>exception</em></span> indicates an unusual condition or an error
condition. <a id="I_indexterm4_id683775" class="indexterm"/>Program control becomes unconditionally transferred or
“thrown” to a specially designated section of code where it’s caught and
handled. In this way, error handling is orthogonal to (or independent of)
the normal flow of the program. We don’t have to have special return
values for all of our methods; errors are handled by a separate mechanism.
Control can be passed a long distance from a deeply nested routine and
handled in a single location when that is desirable, or an error can be
handled immediately at its source. A few standard Java API methods still
return <code class="literal">-1</code> as a special value, but these
are generally limited to situations where we are expecting a special value
and the situation is not really out of bounds.<sup>[<a id="learnjava3-CHP-4-FNOTE-4" href="#ftn.learnjava3-CHP-4-FNOTE-4" class="footnote">10</a>]</sup></p><p>A Java method is required to specify the exceptions it can throw
(i.e., the ones that it doesn’t catch itself), and the compiler makes sure
that callers of the method handle them. In this way, the information about
what errors a method can produce is promoted to the same level of
importance as its argument and return types. You may still decide to punt
and ignore obvious errors, but in Java you must do so explicitly. (We’ll
discuss “runtime exceptions,” which are not required to be declared or
handled by the method, in a moment.)</p><div class="sect2" title="Exceptions and Error Classes"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-4-SECT-5.1"/>Exceptions and Error Classes</h2></div></div></div><p><a id="idx10141" class="indexterm"/> <a id="idx10145" class="indexterm"/> <a id="idx10149" class="indexterm"/> <a id="idx10191" class="indexterm"/>Exceptions are represented by instances of the class
<a id="I_indexterm4_id683888" class="indexterm"/><code class="literal">java.lang.Exception</code> and
its subclasses. Subclasses of <code class="literal">Exception</code> can hold specialized information
(and possibly behavior) for different kinds of exceptional conditions.
However, more often they are simply “logical” subclasses that serve only
to identify a new exception type. <a class="xref" href="ch04s05.html#learnjava3-CHP-4-FIG-1" title="Figure 4-1. The java.lang.Exception subclasses">Figure 4-1</a> shows the subclasses of <code class="literal">Exception</code> in the <a id="I_indexterm4_id683918" class="indexterm"/><code class="literal">java.lang</code> package. It
should give you a feel for how exceptions are organized. Most other
packages define their own exception types, which usually are subclasses
of <code class="literal">Exception</code> itself or of its
important subclass <a id="I_indexterm4_id683936" class="indexterm"/><code class="literal">RuntimeException</code>, which
we’ll get to in a moment.</p><p>For example, an important exception class is <a id="I_indexterm4_id683951" class="indexterm"/><code class="literal">IOException</code> in the
package <a id="I_indexterm4_id683962" class="indexterm"/><code class="literal">java.io</code>. The <code class="literal">IOException</code> class extends <code class="literal">Exception</code> and has many subclasses for typical
I/O problems (such as a <code class="literal">FileNotFoundException</code>) and networking problems
(such as a <code class="literal">Malformed</code><code class="literal">URL</code><code class="literal">Exception</code>). Network exceptions belong to
the <code class="literal">java.net</code> package. Another
important descendant of <code class="literal">IOException</code>
is <a id="I_indexterm4_id684020" class="indexterm"/><code class="literal">RemoteException</code>, which
belongs to the <a id="I_indexterm4_id684031" class="indexterm"/><code class="literal">java.rmi</code> package.
<a id="I_indexterm4_id684042" class="indexterm"/>It is used when problems arise during remote method
invocation (RMI). Throughout this book, we mention exceptions you need
to be aware of as we encounter them.</p><div class="figure"><a id="learnjava3-CHP-4-FIG-1"/><div class="figure-contents"><div class="mediaobject"><a id="I_4_tt168"/><img src="httpatomoreillycomsourceoreillyimages1707613.png" alt="The java.lang.Exception subclasses"/></div></div><p class="title">Figure 4-1. The java.lang.Exception subclasses</p></div><p>An <code class="literal">Exception</code> object is created
by the code at the point where the error condition arises. It can be
designed to hold any information that is necessary to describe the
exceptional condition and also includes a full <span class="emphasis"><em>stack
trace</em></span> for debugging. (A stack trace is the list of all the
methods called and the order in which they were called to reach the
point where the exception was thrown.) The <code class="literal">Exception</code> object is passed as an argument to
the handling block of code, along with the flow of control. This is
where the terms <span class="emphasis"><em>throw</em></span> and
<span class="emphasis"><em>catch</em></span> come from: the <code class="literal">Exception</code> object is thrown from one point in
the code and caught by the other, where execution resumes.</p><p>The Java API also defines the <a id="I_indexterm4_id684106" class="indexterm"/><code class="literal">java.lang.Error</code> class
for unrecoverable errors. The subclasses of <code class="literal">Error</code> in the <code class="literal">java.lang</code> package are shown in <a class="xref" href="ch04s05.html#learnjava3-CHP-4-FIG-2" title="Figure 4-2. The java.lang.Error subclasses">Figure 4-2</a>. A notable <code class="literal">Error</code> type is <a id="I_indexterm4_id684137" class="indexterm"/><code class="literal">AssertionError</code>, which
is used by the Java <a id="I_indexterm4_id684148" class="indexterm"/><code class="literal">assert</code> statement to
indicate a failure (assertions are discussed later in this chapter). A
few other packages define their own subclasses of <code class="literal">Error</code>, but subclasses of <code class="literal">Error</code> are much less common (and less useful)
than subclasses of <code class="literal">Exception</code>. You
generally needn’t worry about these errors in your code (i.e., you do
not have to catch them); they are intended to indicate fatal problems or
virtual machine errors. An error of this kind usually causes the Java
interpreter to display a message and exit. You are actively discouraged
from trying to catch or recover from them because they are supposed to
indicate a fatal program bug, not a routine condition.</p><div class="figure"><a id="learnjava3-CHP-4-FIG-2"/><div class="figure-contents"><div class="mediaobject"><a id="I_4_tt169"/><img src="httpatomoreillycomsourceoreillyimages1707614.png" alt="The java.lang.Error subclasses"/></div></div><p class="title">Figure 4-2. The java.lang.Error subclasses</p></div><p>Both <code class="literal">Exception</code> and <code class="literal">Error</code> are subclasses of <a id="I_indexterm4_id684214" class="indexterm"/><code class="literal">Throwable</code>. The <code class="literal">Throwable</code> class is the base class for objects
that can be “thrown” with the <code class="literal">throw</code>
statement. In general, you should extend only <code class="literal">Exception</code>, <code class="literal">Error</code>, or one of their subclasses.<a id="I_indexterm4_id684248" class="indexterm"/><a id="I_indexterm4_id684255" class="indexterm"/><a id="I_indexterm4_id684262" class="indexterm"/><a id="I_indexterm4_id684269" class="indexterm"/></p></div><div class="sect2" title="Exception Handling"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-4-SECT-5.2"/>Exception Handling</h2></div></div></div><p><a id="idx10151" class="indexterm"/> <a id="idx10190" class="indexterm"/>The <a id="I_indexterm4_id684310" class="indexterm"/><code class="literal">try/catch</code> guarding
statements wrap a block of code and catch designated types of exceptions
that occur within it:</p><a id="I_4_tt170"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code>
<code class="n">readFromFile</code><code class="o">(</code><code class="s">"foo"</code><code class="o">);</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">Exception</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// Handle error</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="s">"Exception while reading file: "</code> <code class="o">+</code> <code class="n">e</code> <code class="o">);</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>In this example, exceptions that occur within the body of the
<code class="literal">try</code> portion of the statement are
directed to the <a id="I_indexterm4_id684345" class="indexterm"/><code class="literal">catch</code> clause for
possible handling. The <code class="literal">catch</code> clause
acts like a method; it specifies as an argument the type of exception it
wants to handle and if it’s invoked, it receives the <code class="literal">Exception</code> object as an argument. Here, we
receive the object in the variable <code class="literal">e</code>
and print it along with a message.</p><p>A <code class="literal">try</code> statement can have
multiple <code class="literal">catch</code> clauses that specify
different types (subclasses) of <code class="literal">Exception</code>:</p><a id="I_4_tt171"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code>
<code class="n">readFromFile</code><code class="o">(</code><code class="s">"foo"</code><code class="o">);</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">FileNotFoundException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// Handle file not found</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">IOException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// Handle read error</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">Exception</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// Handle all other errors</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>The <code class="literal">catch</code> clauses are evaluated
in order, and the first assignable match is taken. At most, one <code class="literal">catch</code> clause is executed, which means that the
exceptions should be listed from most to least specific. In the previous
example, we anticipate that the hypothetical <code class="literal">readFromFile()</code> can throw two different kinds
of exceptions: one for a file not found and another for a more general
read error. In the preceding example, <code class="literal">FileNotFoundException</code> is a subclass of
<code class="literal">IOException</code>, so if the first <code class="literal">catch</code> clause were not there, the exception
would be caught by the second in this case. Similarly, any subclass of
<code class="literal">Exception</code> is assignable to the parent
type <code class="literal">Exception</code>, so the third <code class="literal">catch</code> clause would catch anything passed by
the first two. It acts here like the <code class="literal">default</code> clause in a <code class="literal">switch</code> statement and handles any remaining
possibilities. We’ve shown it here for completeness, but in general you
want to be as specific as possible in the exception types you
catch.</p><p>One beauty of the <code class="literal">try/catch</code>
scheme is that any statement in the <code class="literal">try</code> block can assume that all previous
statements in the block succeeded. A problem won’t arise suddenly
because a programmer forgot to check the return value from a method. If
an earlier statement fails, execution jumps immediately to the <code class="literal">catch</code> clause; later statements are never
executed.</p><p>In Java 7, there is an alternative to using multiple <code class="literal">catch</code> clauses, and that is to handle multiple
discrete exception types in a single <code class="literal">catch</code> clause using the “|” or
syntax:<a id="I_programlisting4_id684514"/></p><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code>
<code class="c1">// read from network...</code>
<code class="c1">// write to file..</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">ZipException</code> <code class="o">|</code> <code class="n">SSLException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="n">logException</code><code class="o">(</code> <code class="n">e</code> <code class="o">);</code>
<code class="o">}</code></pre><p>Using this “|” or syntax, we receive both types of exception in
the same <code class="literal">catch</code> clause. So, what is
the actual type of the <code class="literal">e</code> variable
that we are passing to our log method? (What can we do with it?) In this
case, it will be neither <code class="literal">ZipException</code>
nor <code class="literal">SSLException</code> but <code class="literal">IOException</code>, which is the two exceptions’
nearest common ancestor (the closest parent class type to which they are
both assignable). In many cases, the nearest common type among the two
or more argument exception types may simply be <code class="literal">Exception</code>, the parent of all exception types.
The difference between catching these discrete exception types with a
multiple-type <code class="literal">catch</code> clause and simply
catching the common parent exception type is that we are limiting our
<code class="literal">catch</code> to only these specifically
enumerated exception types and we will not catch all the other <code class="literal">IOException</code> types, as would be the alternative
in this case. The combination of multiple-type <code class="literal">catch</code> and ordering your <code class="literal">catch</code> clauses from most specific to most broad
(“narrow” to “wide”) types gives you great flexibility to structure your
<code class="literal">catch</code> clauses to consolidate handling
logic where it is appropriate and to not repeat code. There are more
nuances to this feature, and we will return to it after we have
discussed “throwing” and “rethrowing” exceptions.<a id="I_indexterm4_id684604" class="indexterm"/><a id="I_indexterm4_id684611" class="indexterm"/></p></div><div class="sect2" title="Bubbling Up"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-4-SECT-5.3"/>Bubbling Up</h2></div></div></div><p><a id="idx10138" class="indexterm"/> <a id="idx10146" class="indexterm"/> <a id="idx10187" class="indexterm"/>What if we hadn’t caught the exception? Where would it
have gone? Well, if there is no enclosing <a id="I_indexterm4_id684664" class="indexterm"/><code class="literal">try/catch</code> statement,
the exception pops up from the method in which it originated and is
thrown from that method up to its caller. If that point in the calling
method is within a <code class="literal">try</code> clause,
control passes to the corresponding <code class="literal">catch</code> clause. Otherwise, the exception
continues propagating up the call stack, from one method to its caller.
In this way, the exception bubbles up until it’s caught, or until it
pops out of the top of the program, terminating it with a runtime error
message. There’s a bit more to it than that because in this case, the
compiler might have forced us to deal with it along the way, but we’ll
get back to that in a moment.</p><p>Let’s look at another example. In <a class="xref" href="ch04s05.html#learnjava3-CHP-4-FIG-3" title="Figure 4-3. Exception propagation">Figure 4-3</a>, the method <code class="literal">getContent()</code> invokes the method <code class="literal">openConnection()</code> from within a <code class="literal">try/catch</code> statement. In turn, <code class="literal">openConnection()</code> invokes the method <code class="literal">sendRequest()</code>, which calls the method <code class="literal">write()</code> to send some data.</p><div class="figure"><a id="learnjava3-CHP-4-FIG-3"/><div class="figure-contents"><div class="mediaobject"><a id="I_4_tt172"/><img src="httpatomoreillycomsourceoreillyimages1707615.png" alt="Exception propagation"/></div></div><p class="title">Figure 4-3. Exception propagation</p></div><p>In this figure, the second call to <code class="literal">write()</code> throws an <code class="literal">IOException</code>. Since <code class="literal">sendRequest()</code> doesn’t contain a <code class="literal">try/catch</code> statement to handle the exception,
it’s thrown again from the point where it was called in the method
<code class="literal">openConnection()</code>. Since <code class="literal">openConnection()</code> doesn’t catch the exception
either, it’s thrown once more. Finally, it’s caught by the <code class="literal">try</code> statement in <code class="literal">getContent()</code> and handled by its <code class="literal">catch</code> clause. Notice that each throwing method
must declare with a “throws” clause that it can throw the particular
type of exception. We’ll discuss this shortly.<a id="I_indexterm4_id684815" class="indexterm"/><a id="I_indexterm4_id684822" class="indexterm"/><a id="I_indexterm4_id684829" class="indexterm"/></p></div><div class="sect2" title="Stack Traces"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-4-SECT-5.4"/>Stack Traces</h2></div></div></div><p><a id="idx10152" class="indexterm"/> <a id="idx10173" class="indexterm"/> <a id="idx10193" class="indexterm"/>Because an exception can bubble up quite a distance before
it is caught and handled, we may need a way to determine exactly where
it was thrown. It’s also very important to know the context of how the
point of the exception was reached; that is, which methods called which
methods to get to that point. For these kinds of debugging and logging
purposes, all exceptions can dump a stack trace that lists their method
of origin and all the nested method calls it took to arrive there. Most
commonly, the user sees a stack trace when it is printed using the
<a id="I_indexterm4_id684888" class="indexterm"/><code class="literal">printStackTrace()</code>
method.</p><a id="I_4_tt173"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code>
<code class="c1">// complex, deeply nested task</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">Exception</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// dump information about exactly where the exception occurred</code>
<code class="n">e</code><code class="o">.</code><code class="na">printStackTrace</code><code class="o">(</code> <code class="n">System</code><code class="o">.</code><code class="na">err</code> <code class="o">);</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>For example, the stack trace for an exception might look like
this:</p><a id="I_4_tt174"/><pre class="programlisting"> <code class="n">java</code><code class="o">.</code><code class="na">io</code><code class="o">.</code><code class="na">FileNotFoundException</code><code class="o">:</code> <code class="n">myfile</code><code class="o">.</code><code class="na">xml</code>
<code class="n">at</code> <code class="n">java</code><code class="o">.</code><code class="na">io</code><code class="o">.</code><code class="na">FileInputStream</code><code class="o">.<</code><code class="n">init</code><code class="o">>(</code><code class="n">FileInputStream</code><code class="o">.</code><code class="na">java</code><code class="o">)</code>
<code class="n">at</code> <code class="n">java</code><code class="o">.</code><code class="na">io</code><code class="o">.</code><code class="na">FileInputStream</code><code class="o">.<</code><code class="n">init</code><code class="o">>(</code><code class="n">FileInputStream</code><code class="o">.</code><code class="na">java</code><code class="o">)</code>
<code class="n">at</code> <code class="n">MyApplication</code><code class="o">.</code><code class="na">loadFile</code><code class="o">(</code><code class="n">MyApplication</code><code class="o">.</code><code class="na">java</code><code class="o">:</code><code class="mi">137</code><code class="o">)</code>
<code class="n">at</code> <code class="n">MyApplication</code><code class="o">.</code><code class="na">main</code><code class="o">(</code><code class="n">MyApplication</code><code class="o">.</code><code class="na">java</code><code class="o">:</code><code class="mi">5</code><code class="o">)</code></pre><p>This stack trace indicates that the <code class="literal">main()</code> method of the class <code class="literal">MyApplication</code> called the method <code class="literal">loadFile()</code>. The <code class="literal">loadFile()</code> method then tried to construct a
<code class="literal">FileInputStream</code>, which threw the
<code class="literal">FileNotFoundException</code>. Note that once
the stack trace reaches Java system classes (like <code class="literal">FileInputStream</code>), the line numbers may be
lost. This can also happen when the code is optimized by some virtual
machines. Usually, there is a way to disable the optimization
temporarily to find the exact line numbers. However, in tricky
situations, changing the timing of the application can affect the
problem you’re trying to debug, and other debugging techniques may be
required.</p><p><a id="I_indexterm4_id684974" class="indexterm"/>Methods on the exception allow you to retrieve the stack
trace information programmatically as well by using the <code class="literal">Throwable getStackTrace()</code> method. (<code class="literal">Throwable</code> is the base class of <code class="literal">Exception</code> and <code class="literal">Error</code>.) This method returns an array of
<a id="I_indexterm4_id685004" class="indexterm"/><code class="literal">StackTraceElement</code>
objects, each of which represents a method call on the stack. You can
ask a <code class="literal">StackTraceElement</code> for details
about that method’s location using the methods <code class="literal">getFileName()</code>, <code class="literal">getClassName()</code>, <code class="literal">getMethodName()</code>, and <code class="literal">getLineNumber()</code>. Element zero of the array is
the top of the stack, the final line of code that caused the exception;
subsequent elements step back one method call each until the original
<code class="literal">main()</code> method is reached.<a id="I_indexterm4_id685051" class="indexterm"/><a id="I_indexterm4_id685058" class="indexterm"/><a id="I_indexterm4_id685065" class="indexterm"/></p></div><div class="sect2" title="Checked and Unchecked Exceptions"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-4-SECT-5.5"/>Checked and Unchecked Exceptions</h2></div></div></div><p><a id="idx10140" class="indexterm"/> <a id="idx10148" class="indexterm"/> <a id="idx10189" class="indexterm"/> <a id="idx10218" class="indexterm"/>We mentioned earlier that Java forces us to be explicit
about our error handling, but it’s not necessary to require that every
conceivable type of error be handled explicitly in every situation. Java
exceptions are therefore divided into two categories:
<span class="emphasis"><em>checked</em></span> and <span class="emphasis"><em>unchecked</em></span>. Most
application-level exceptions are checked, which means that any method
that throws one, either by generating it itself (as we’ll discuss later)
or by ignoring one that occurs within it, must declare that it can throw
that type of exception in a special <code class="literal">throws</code> clause in its method declaration. We
haven’t yet talked in detail about declaring methods (see <a class="xref" href="ch05.html" title="Chapter 5. Objects in Java">Chapter 5</a>). For now, all you need to know is that
methods have to declare the checked exceptions they can throw or allow
to be thrown.</p><p>Again in <a class="xref" href="ch04s05.html#learnjava3-CHP-4-FIG-3" title="Figure 4-3. Exception propagation">Figure 4-3</a>, notice that
the methods <code class="literal">openConnection()</code> and
<code class="literal">sendRequest()</code> both specify that they
can throw an <code class="literal">IOException</code>. If we had
to throw multiple types of exceptions, we could declare them separated
by commas:</p><a id="I_4_tt175"/><pre class="programlisting"> <code class="kt">void</code> <code class="nf">readFile</code><code class="o">(</code> <code class="n">String</code> <code class="n">s</code> <code class="o">)</code> <code class="kd">throws</code> <code class="n">IOException</code><code class="o">,</code> <code class="n">InterruptedException</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>The <code class="literal">throws</code> clause tells the
compiler that a method is a possible source of that type of checked
exception and that anyone calling that method must be prepared to deal
with it. The caller must then either use a <code class="literal">try/catch</code> block to handle it, or it must, in
turn, declare that it can throw the exception from itself.</p><p>In contrast, exceptions that are subclasses of either the class
<code class="literal">java.lang.RuntimeException</code> or the
class <code class="literal">java.lang.Error</code> are unchecked.
See <a class="xref" href="ch04s05.html#learnjava3-CHP-4-FIG-1" title="Figure 4-1. The java.lang.Exception subclasses">Figure 4-1</a> for the subclasses of
<code class="literal">RuntimeException</code>. (Subclasses of
<code class="literal">Error</code> are generally reserved for
serious class loading or runtime system problems.) It’s not a
compile-time error to ignore the possibility of these exceptions;
methods also don’t have to declare they can throw them. In all other
respects, unchecked exceptions behave the same as other exceptions. We
are free to catch them if we wish, but in this case we aren’t required
to.</p><p>Checked exceptions are intended to cover application-level
problems, such as missing files and unavailable hosts. As good
programmers (and upstanding citizens), we should design software to
recover gracefully from these kinds of conditions. Unchecked exceptions
are intended for system-level problems, such as “out of memory” and
“array index out of bounds.” While these may indicate application-level
programming errors, they can occur almost anywhere and usually aren’t
possible to recover from. Fortunately, because they are unchecked
exceptions, you don’t have to wrap every one of your array-index
operations in a <code class="literal">try/catch</code> statement
(or declare all of the calling methods as a potential source of
them).</p><p>To sum up, checked exceptions are problems that a reasonable
application should try to handle gracefully; unchecked exceptions
(runtime exceptions or errors) are problems from which we would not
normally expect our software to recover. Error types are those
explicitly intended to be conditions that we should not normally try to
handle or recover from.<a id="I_indexterm4_id685267" class="indexterm"/><a id="I_indexterm4_id685274" class="indexterm"/><a id="I_indexterm4_id685281" class="indexterm"/><a id="I_indexterm4_id685288" class="indexterm"/></p></div><div class="sect2" title="Throwing Exceptions"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-4-SECT-5.6"/>Throwing Exceptions</h2></div></div></div><p><a id="idx10153" class="indexterm"/> <a id="idx10194" class="indexterm"/> <a id="idx10212" class="indexterm"/>We can throw our own exceptions—either instances of
<code class="literal">Exception</code>, one of its existing
subclasses, or our own specialized exception classes. All we have to do
is create an instance of the <code class="literal">Exception</code> and throw it with the <a id="I_indexterm4_id685352" class="indexterm"/><code class="literal">throw</code> statement:</p><a id="I_4_tt176"/><pre class="programlisting"> <code class="k">throw</code> <code class="k">new</code> <code class="nf">IOException</code><code class="o">();</code></pre><p>Execution stops and is transferred to the nearest enclosing
<code class="literal">try/catch</code> statement that can handle
the exception type. (There is little point in keeping a reference to the
<code class="literal">Exception</code> object we’ve created here.)
An alternative constructor lets us specify a string with an error
message:</p><a id="I_4_tt177"/><pre class="programlisting"> <code class="k">throw</code> <code class="k">new</code> <code class="nf">IOException</code><code class="o">(</code><code class="s">"Sunspots!"</code><code class="o">);</code></pre><p>You can retrieve this string by using the <a id="I_indexterm4_id685399" class="indexterm"/><code class="literal">Exception</code> object’s
<a id="I_indexterm4_id685410" class="indexterm"/><code class="literal">getMessage()</code> method.
Often, though, you can just print (or <code class="literal">toString()</code>) the exception object itself to get
the message and stack trace.</p><p>By convention, all types of <code class="literal">Exception</code> have a <code class="literal">String</code> constructor like this. The preceding
<code class="literal">String</code> message is not very useful.
Normally, it will throw a more specific subclass <code class="literal">Exception</code>, which captures details or at least
a more specific string explanation. Here’s another example:</p><a id="I_4_tt178"/><pre class="programlisting"> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">checkRead</code><code class="o">(</code> <code class="n">String</code> <code class="n">s</code> <code class="o">)</code> <code class="o">{</code>
<code class="k">if</code> <code class="o">(</code> <code class="k">new</code> <code class="n">File</code><code class="o">(</code><code class="n">s</code><code class="o">).</code><code class="na">isAbsolute</code><code class="o">()</code> <code class="o">||</code> <code class="o">(</code><code class="n">s</code><code class="o">.</code><code class="na">indexOf</code><code class="o">(</code><code class="s">".."</code><code class="o">)</code> <code class="o">!=</code> <code class="o">-</code><code class="mi">1</code><code class="o">)</code> <code class="o">)</code>
<code class="k">throw</code> <code class="k">new</code> <code class="nf">SecurityException</code><code class="o">(</code>
<code class="s">"Access to file : "</code><code class="o">+</code> <code class="n">s</code> <code class="o">+</code><code class="s">" denied."</code><code class="o">);</code>
<code class="o">}</code></pre><p>In this code, we partially implement a method to check for an
illegal path. If we find one, we throw a <a id="I_indexterm4_id685466" class="indexterm"/><code class="literal">SecurityException</code> with
some information about the transgression.</p><p>Of course, we could include any other information that is useful
in our own specialized subclasses of <code class="literal">Exception</code>. Often, though, just having a new
type of exception is good enough because it’s sufficient to help direct
the flow of control. For example, if we are building a parser, we might
want to make our own kind of exception to indicate a particular kind of
failure:</p><a id="I_4_tt179"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">ParseException</code> <code class="kd">extends</code> <code class="n">Exception</code> <code class="o">{</code>
<code class="n">ParseException</code><code class="o">()</code> <code class="o">{</code>
<code class="kd">super</code><code class="o">();</code>
<code class="o">}</code>
<code class="n">ParseException</code><code class="o">(</code> <code class="n">String</code> <code class="n">desc</code> <code class="o">)</code> <code class="o">{</code>
<code class="kd">super</code><code class="o">(</code> <code class="n">desc</code> <code class="o">);</code>
<code class="o">}</code>
<code class="o">}</code></pre><p>See <a class="xref" href="ch05.html" title="Chapter 5. Objects in Java">Chapter 5</a> for a full description of
classes and class constructors. The body of our <code class="literal">Exception</code> class here simply allows a
<a id="I_indexterm4_id685514" class="indexterm"/><code class="literal">ParseException</code> to be
created in the conventional ways we’ve created exceptions previously
(either generically or with a simple string description). Now that we
have our new exception type, we can guard like this:</p><a id="I_4_tt180"/><pre class="programlisting"> <code class="c1">// Somewhere in our code</code>
<code class="o">...</code>
<code class="k">try</code> <code class="o">{</code>
<code class="n">parseStream</code><code class="o">(</code> <code class="n">input</code> <code class="o">);</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">ParseException</code> <code class="n">pe</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// Bad input...</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">IOException</code> <code class="n">ioe</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// Low-level communications problem</code>
<code class="o">}</code></pre><p>As you can see, although our new exception doesn’t currently hold
any specialized information about the problem (it certainly could), it
does let us distinguish a parse error from an arbitrary I/O error in the
same chunk of code.</p><div class="sect3" title="Chaining and rethrowing exceptions"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-4-SECT-5.6.1"/>Chaining and rethrowing exceptions</h3></div></div></div><p><a id="idx10139" class="indexterm"/> <a id="idx10147" class="indexterm"/> <a id="idx10188" class="indexterm"/>Sometimes you’ll want to take some action based on an
exception and then turn around and throw a new exception in its place.
This is common when building frameworks where low-level detailed
exceptions are handled and represented by higher-level exceptions that
can be managed more easily. For example, you might want to catch an
<code class="literal">IOException</code> in a communications
package, possibly perform some cleanup, and ultimately throw a higher-level
exception of your own, maybe something like <code class="literal">LostServerConnection</code>.</p><p>You can do this in the obvious way by simply catching the
exception and then throwing a new one, but then you lose important
information, including the stack trace of the original “causal”
exception. To deal with this, you can use the technique of
<span class="emphasis"><em>exception chaining</em></span>. This means that you include
the causal exception in the new exception that you throw. Java has
explicit support for exception chaining. The base <code class="literal">Exception</code> class can be constructed with an
exception as an argument or the standard <code class="literal">String</code> message and an exception:</p><a id="I_4_tt181"/><pre class="programlisting"> <code class="k">throw</code> <code class="k">new</code> <code class="nf">Exception</code><code class="o">(</code> <code class="s">"Here's the story..."</code><code class="o">,</code> <code class="n">causalException</code> <code class="o">);</code></pre><p>You can get access to the wrapped exception later with the
<a id="I_indexterm4_id685647" class="indexterm"/><code class="literal">getCause()</code> method.
More importantly, Java automatically prints both exceptions and their
respective stack traces if you print the exception or if it is shown
to the user.</p><p>You can add this kind of constructor to your own exception
subclasses (delegating to the parent constructor) or you can take
advantage of this pattern by using the <a id="I_indexterm4_id685663" class="indexterm"/><code class="literal">Throwable</code> method
<a id="I_indexterm4_id685674" class="indexterm"/><code class="literal">initCause()</code> to set
the causal exception explicitly after constructing your exception and
before throwing it:</p><a id="I_4_tt182"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code>
<code class="c1">// ...</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">IOException</code> <code class="n">cause</code> <code class="o">)</code> <code class="o">{</code>
<code class="n">Exception</code> <code class="n">e</code> <code class="o">=</code>
<code class="k">new</code> <code class="nf">IOException</code><code class="o">(</code><code class="s">"What we have here is a failure to communicate..."</code><code class="o">);</code>
<code class="n">e</code><code class="o">.</code><code class="na">initCause</code><code class="o">(</code> <code class="n">cause</code> <code class="o">);</code>
<code class="k">throw</code> <code class="n">e</code><code class="o">;</code>
<code class="o">}</code></pre><p>Sometimes it’s enough to simply do some logging or take some
action and then rethrow the original exception:<a id="I_programlisting4_id685700"/></p><pre class="programlisting"><code class="k">try</code> <code class="o">{</code>
<code class="c1">// ...</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">IOException</code> <code class="n">cause</code> <code class="o">)</code> <code class="o">{</code>
<code class="n">log</code><code class="o">(</code> <code class="n">e</code> <code class="o">);</code> <code class="c1">// Log it</code>
<code class="k">throw</code> <code class="n">e</code><code class="o">;</code> <code class="c1">// rethrow it</code>
<code class="o">}</code></pre><p>But be aware that if you do that, the stack trace
included in the exception will show the new throw location as the
origin.</p></div><div class="sect3" title="Narrowed rethrow"><div class="titlepage"><div><div><h3 class="title"><a id="id1106011"/>Narrowed rethrow</h3></div></div></div><p>Prior to Java 7 if you wanted to handle a bunch of exception
types in a single <code class="literal">catch</code> clause and
then rethrow the original exception, you would inevitably end up
widening the declared exception type to what was required to catch
them all or having to do a lot of work to avoid that. In Java 7, the
compiler has become smarter and can now do most of the work for us by
allowing us to narrow the type of exceptions thrown back to the
original types in most cases. This is best explained by
example:<a id="I_programlisting4_id685725"/></p><pre class="programlisting"><code class="kt">void</code> <code class="nf">myMethod</code><code class="o">()</code> <code class="kd">throws</code> <code class="n">ZipException</code><code class="o">,</code> <code class="n">SSLException</code>
<code class="o">{</code>
<code class="k">try</code> <code class="o">{</code>
<code class="c1">// Possible cause of ZipException or SSLException</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">Exception</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="n">log</code><code class="o">(</code> <code class="n">e</code> <code class="o">);</code>
<code class="k">throw</code> <code class="n">e</code><code class="o">;</code>
<code class="o">}</code>
<code class="o">}</code></pre><p>In this example, we are exceedingly lazy and simply catch
all exceptions with a broad catch <code class="literal">Exception</code> clause in order to log them prior
to rethrowing. Prior to Java 7, the compiler would have insisted that
the <code class="literal">throws</code> clause of our method
declare that it throws the broad <code class="literal">Exception</code> type as well. However, the Java
compiler is now smart enough in most cases to analyze the actual types
of exceptions that may be thrown and allow us to prescribe the precise
set of types. The same would be true if we had used the mutiple-type
<code class="literal">catch</code> clause in this example, as
you might have guessed. The preceding is a bit less intuitive, but
very useful in shoring up the specificity of exception handling of
code, including code written prior to Java 7, without requiring
potentially tricky reworking of <code class="literal">catch</code> clauses.<a id="I_indexterm4_id685768" class="indexterm"/><a id="I_indexterm4_id685775" class="indexterm"/><a id="I_indexterm4_id685782" class="indexterm"/><a id="I_indexterm4_id685789" class="indexterm"/><a id="I_indexterm4_id685796" class="indexterm"/><a id="I_indexterm4_id685803" class="indexterm"/></p></div></div><div class="sect2" title="try Creep"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-4-SECT-5.7"/>try Creep</h2></div></div></div><p><a id="idx10154" class="indexterm"/> <a id="idx10195" class="indexterm"/>The <code class="literal">try</code> statement
imposes a condition on the statements that it guards. It says that if an
exception occurs within it, the remaining statements are abandoned. This
has consequences for local variable initialization. If the compiler
can’t determine whether a local variable assignment placed inside a
<code class="literal">try/catch</code> block will happen, it won’t
let us use the variable. For example:</p><a id="I_4_tt183"/><pre class="programlisting"> <code class="kt">void</code> <code class="nf">myMethod</code><code class="o">()</code> <code class="o">{</code>
<code class="kt">int</code> <code class="n">foo</code><code class="o">;</code>
<code class="k">try</code> <code class="o">{</code>
<code class="n">foo</code> <code class="o">=</code> <code class="n">getResults</code><code class="o">();</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">Exception</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="kt">int</code> <code class="n">bar</code> <code class="o">=</code> <code class="n">foo</code><code class="o">;</code> <code class="c1">// Compile-time error: foo may not have been initialized</code></pre><p>In this example, we can’t use <code class="literal">foo</code> in the indicated place because there’s a
chance it was never assigned a value. One obvious option is to move the
assignment inside the <code class="literal">try</code>
statement:</p><a id="I_4_tt184"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code>
<code class="n">foo</code> <code class="o">=</code> <code class="n">getResults</code><code class="o">();</code>
<code class="kt">int</code> <code class="n">bar</code> <code class="o">=</code> <code class="n">foo</code><code class="o">;</code> <code class="c1">// Okay because we get here only</code>
<code class="c1">// if previous assignment succeeds</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">Exception</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>Sometimes this works just fine. However, now we have the same
problem if we want to use <code class="literal">bar</code> later
in <code class="literal">myMethod()</code>. If we’re not careful,
we might end up pulling everything into the <code class="literal">try</code> statement. The situation changes, however,
if we transfer control out of the method in the <code class="literal">catch</code> clause:</p><a id="I_4_tt185"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code>
<code class="n">foo</code> <code class="o">=</code> <code class="n">getResults</code><code class="o">();</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">Exception</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="o">...</code>
<code class="k">return</code><code class="o">;</code>
<code class="o">}</code>
<code class="kt">int</code> <code class="n">bar</code> <code class="o">=</code> <code class="n">foo</code><code class="o">;</code> <code class="c1">// Okay because we get