📄 chapter09.html
字号:
the previous
one.</FONT><A NAME="_Toc312374119"></A><A NAME="_Toc375545369"></A><A NAME="_Toc408018596"></A><BR></P></DIV>
<A NAME="Heading289"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Rethrowing an exception<BR><A NAME="Index931"></A><A NAME="Index932"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Sometimes you’ll want to
rethrow the exception that you just caught, particularly when you use
<B>Exception</B> to catch any exception. Since you already have the handle to
the current exception, you can simply re-throw that handle:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>catch</font>(Exception e) {
System.out.println(<font color=#004488>"An exception was thrown"</font>);
<font color=#0000ff>throw</font> e;
}</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Rethrowing an exception causes the
exception to go to the exception handlers in the next-higher context. Any
further <B>catch</B> clauses for the same <B>try</B> block are still ignored. In
addition, everything about the exception object is preserved, so the handler at
the higher context that catches the specific exception type can extract all the
information from that object.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you simply re-throw the current
exception, the information that you print about that exception in
<A NAME="Index933"></A><A NAME="Index934"></A><B>printStackTrace( )
</B>will pertain to the exception’s origin, not the place where you
re-throw it. If you want to install new stack trace information, you can do so
by calling
<A NAME="Index935"></A><A NAME="Index936"></A><B>fillInStackTrace( )</B>,
which returns an exception object that it creates by stuffing the current stack
information into the old exception object. Here’s what it looks
like:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: Rethrowing.java</font>
<font color=#009900>// Demonstrating fillInStackTrace()</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Rethrowing {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> f() <font color=#0000ff>throws</font> Exception {
System.out.println(
<font color=#004488>"originating the exception in f()"</font>);
<font color=#0000ff>throw</font> <font color=#0000ff>new</font> Exception(<font color=#004488>"thrown from f()"</font>);
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> g() <font color=#0000ff>throws</font> Throwable {
<font color=#0000ff>try</font> {
f();
} <font color=#0000ff>catch</font>(Exception e) {
System.out.println(
<font color=#004488>"Inside g(), e.printStackTrace()"</font>);
e.printStackTrace();
<font color=#0000ff>throw</font> e; <font color=#009900>// 17</font>
<font color=#009900>// throw e.fillInStackTrace(); // 18</font>
}
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font>
main(String[] args) <font color=#0000ff>throws</font> Throwable {
<font color=#0000ff>try</font> {
g();
} <font color=#0000ff>catch</font>(Exception e) {
System.out.println(
<font color=#004488>"Caught in main, e.printStackTrace()"</font>);
e.printStackTrace();
}
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The important line numbers are
marked inside of comments. With line 17 un-commented (as shown), the output
is:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>originating the exception in f()
Inside g(), e.printStackTrace()
java.lang.Exception: thrown from f()
at Rethrowing.f(Rethrowing.java:8)
at Rethrowing.g(Rethrowing.java:12)
at Rethrowing.main(Rethrowing.java:24)
Caught in main, e.printStackTrace()
java.lang.Exception: thrown from f()
at Rethrowing.f(Rethrowing.java:8)
at Rethrowing.g(Rethrowing.java:12)
at Rethrowing.main(Rethrowing.java:24)</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">So the exception stack trace always
remembers its true point of origin, no matter how many times it gets
rethrown.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">With line 17 commented and line 18
un-commented, <B>fillInStackTrace( )</B> is used instead, and the result
is:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>originating the exception in f()
Inside g(), e.printStackTrace()
java.lang.Exception: thrown from f()
at Rethrowing.f(Rethrowing.java:8)
at Rethrowing.g(Rethrowing.java:12)
at Rethrowing.main(Rethrowing.java:24)
Caught in main, e.printStackTrace()
java.lang.Exception: thrown from f()
at Rethrowing.g(Rethrowing.java:18)
at Rethrowing.main(Rethrowing.java:24)</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Because of
<B>fillInStackTrace( )</B>, line 18 becomes the new
<A NAME="Index937"></A>point of origin of the exception.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The class <B>Throwable</B> must
appear in the exception specification for <B>g( )</B> and
<B>main( )</B> because <B>fillInStackTrace( )</B> produces a handle to
a <B>Throwable</B> object. Since <A NAME="Index938"></A><B>Throwable</B> is a
base class of <B>Exception</B>, it’s possible to get an object
that’s a <B>Throwable</B> but <I>not</I> an <B>Exception</B>, so the
handler for <B>Exception</B> in <B>main( ) </B>might miss it. To make sure
everything is in order, the compiler forces an exception specification for
<B>Throwable</B>. For example, the exception in the following program is
<I>not</I> caught in <B>main( )</B>:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: ThrowOut.java</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> ThrowOut {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font>
main(String[] args) <font color=#0000ff>throws</font> Throwable {
<font color=#0000ff>try</font> {
<font color=#0000ff>throw</font> <font color=#0000ff>new</font> Throwable();
} <font color=#0000ff>catch</font>(Exception e) {
System.out.println(<font color=#004488>"Caught in main()"</font>);
}
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It’s also possible to rethrow
a different exception from the one you caught. If you do this, you get a similar
effect as when you use <B>fillInStackTrace( )</B>: the information about
the original site of the exception is lost, and what you’re left with is
the information pertaining to the new <B>throw</B>:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: RethrowNew.java</font>
<font color=#009900>// Rethrow a different object from the one that</font>
<font color=#009900>// was caught</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> RethrowNew {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> f() <font color=#0000ff>throws</font> Exception {
System.out.println(
<font color=#004488>"originating the exception in f()"</font>);
<font color=#0000ff>throw</font> <font color=#0000ff>new</font> Exception(<font color=#004488>"thrown from f()"</font>);
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
<font color=#0000ff>try</font> {
f();
} <font color=#0000ff>catch</font>(Exception e) {
System.out.println(
<font color=#004488>"Caught in main, e.printStackTrace()"</font>);
e.printStackTrace();
<font color=#0000ff>throw</font> <font color=#0000ff>new</font> NullPointerException(<font color=#004488>"from main"</font>);
}
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The output is:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>originating the exception in f()
Caught in main, e.printStackTrace()
java.lang.Exception: thrown from f()
at RethrowNew.f(RethrowNew.java:8)
at RethrowNew.main(RethrowNew.java:13)
java.lang.NullPointerException: from main
at RethrowNew.main(RethrowNew.java:18)</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The final exception knows only that
it came from <B>main( )</B>, and not from <B>f( )</B>. Note that
<B>Throwable</B> isn’t necessary in any of the exception
specifications.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You never have to worry about
cleaning up the previous exception, or any exceptions for that matter.
They’re all heap-based objects created with <B>new</B>, so the garbage
collector automatically cleans them all
up.</FONT><A NAME="_Toc375545370"></A><A NAME="_Toc408018597"></A><BR></P></DIV>
<A NAME="Heading290"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Standard Java exceptions</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Java contains a class called
<B>Throwable</B> that describes anything that can be thrown as an exception.
There are two general types of <B>Throwable</B> objects (“types of”
= “inherited from”). <A NAME="Index939"></A><B>Error</B> represents
compile-time and system errors that you don’t worry about catching (except
in special cases). <A NAME="Index940"></A><B>Exception</B> is the basic type
that can be thrown from any of the standard Java library class methods and from
your methods and run-time accidents.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The best way to get an overview of
the exceptions is to browse online Java documentation from
<I>http://java.sun.com.</I> (Of course, it’s easier to download it first.)
It’s worth doing this once just to get a feel for the various exceptions,
but you’ll soon see that there isn’t anything special between one
exception and the next except for the name. Also, the number of exceptions in
Java keeps expanding; basically it’s pointless to print them in a book.
Any new library you get from a third-party vendor will probably have its own
exceptions as well. The important thing to understand is the concept and what
you should do with the exceptions.</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>java.lang.Exception </PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This is the basic exception class
your program can catch. Other exceptions are derived from this. The basic idea
is that the name of the exception represents the problem that occurred and the
exception name is intended to be relatively self-explanatory. The exceptions are
not all defined in <B>java.lang</B>; some are created to support other libraries
such as <B>util</B>, <B>net,</B> and <B>io</B>, which you can see from their
full class names or what they are inherited from. For example, all IO exceptions
are inherited from
<B>java.io.IOException</B>.</FONT><A NAME="_Toc375545372"></A><A NAME="_Toc408018598"></A><BR></P></DIV>
<A NAME="Heading291"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
The special case of RuntimeException</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The first example in this chapter
was</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>if</font>(t == <font color=#0000ff>null</font>)
<font color=#0000ff>throw</font> <font color=#0000ff>new</font> NullPointerException();</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It can be a bit horrifying to think
that you must check for <B>null</B> on every handle that is passed into a method
(since you can’t know if the caller has passed you a valid handle).
Fortunately, you don’t – this is part of the standard run-time
checking that Java performs for you, and if any call is made to a null handle,
Java will automatically throw a
<A NAME="Index941"></A><A NAME="Index942"></A><B>NullPointerException</B>. So
the above bit of code is always superfluous. </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There’s a whole group of
exception types that are in this category. They’re always thrown
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -