📄 chap10.htm
字号:
you’ll first use <B>new</B> to create<B> </B>an object that represents the
error condition. You give the resulting reference to <B>throw</B>. The object
is, in effect, “returned” from the method, even though that object
type isn’t normally what the method is designed to return. A simplistic
way to think about exception handling is as an alternate return mechanism,
although you get into trouble if you take that analogy too far. You can also
exit from ordinary scopes by throwing an exception. But a value is returned, and
the method or scope exits.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I11'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I12>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Any similarity to an ordinary return from
a method ends here, because <I>where</I> you return is someplace completely
different from where you return for a normal method call. (You end up in an
appropriate exception handler that might be miles away—many levels lower
on the call stack—from where the exception was thrown.)
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I12'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I13>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In addition, you can throw any type of
<B>Throwable</B> object that you want. Typically, you’ll throw a different
class of exception for each different type of error. The information about the
error is represented both inside the exception object and implicitly in the type
of exception object chosen, so someone in the bigger context can figure out what
to do with your exception. (Often, the only information is the type of exception
object, and nothing meaningful is stored within the exception object.)
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I13'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I14>
</FONT><A NAME="_Toc305593298"></A><A NAME="_Toc305628770"></A><A NAME="_Toc312374113"></A><A NAME="_Toc375545364"></A><A NAME="_Toc481064716"></A><BR></P></DIV>
<A NAME="Heading334"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Catching an exception<BR><A NAME="Index1057"></A><A NAME="Index1058"></A></H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If a method throws an exception, it must
assume that exception is “caught” and dealt with. One of the
advantages of Java exception handling is that it allows you to concentrate on
the problem you’re trying to solve in one place, and then deal with the
errors from that code in another place.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I14'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I15>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To see how an exception is caught, you
must first understand the concept of a
<A NAME="Index1059"></A><A NAME="Index1060"></A><I>guarded region,</I> which is
a section of code that might produce exceptions, and which is followed by the
code to handle those exceptions.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I15'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I16>
</FONT><A NAME="_Toc312374114"></A><A NAME="_Toc375545365"></A><A NAME="_Toc481064717"></A><BR></P></DIV>
<A NAME="Heading335"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
The try block</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you’re inside a method and you
throw an exception (or another method you call within this method throws an
exception), that method will exit in the process of throwing. If you don’t
want a <B>throw </B>to exit the method, you can set up a special block within
that method to capture the exception. This is called the <I>try</I>
<I>block<A NAME="Index1061"></A><A NAME="Index1062"></A></I> because you
“try” your various method calls there. The try block is an ordinary
scope, preceded by the keyword <B>try</B>:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>try</font> {
<font color=#009900>// Code that might generate exceptions</font>
}</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you were checking for errors carefully
in a programming language that didn’t support exception handling,
you’d have to surround every method call with setup and error testing
code, even if you call the same method several times. With exception handling,
you put everything in a try block and capture all the exceptions in one place.
This means your code is a lot easier to write and easier to read because the
goal of the code is not confused with the error checking.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I16'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I17>
</FONT><A NAME="_Toc312374115"></A><A NAME="_Toc375545366"></A><A NAME="_Toc481064718"></A><BR></P></DIV>
<A NAME="Heading336"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Exception handlers</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Of course, the thrown exception must end
up someplace. This “place” is the <I>exception
handler<A NAME="Index1063"></A><A NAME="Index1064"></A>,</I> and there’s
one for every exception type you want to catch. Exception handlers immediately
follow the try block and are denoted by the keyword
<B>catch<A NAME="Index1065"></A></B>:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>try</font> {
<font color=#009900>// Code that might generate exceptions</font>
} <font color=#0000ff>catch</font>(Type1 id1) {
<font color=#009900>// Handle exceptions of Type1</font>
} <font color=#0000ff>catch</font>(Type2 id2) {
<font color=#009900>// Handle exceptions of Type2</font>
} <font color=#0000ff>catch</font>(Type3 id3) {
<font color=#009900>// Handle exceptions of Type3</font>
}
<font color=#009900>// etc...</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Each catch clause (exception handler) is
like a little method that takes one and only one argument of a particular type.
The identifier (<B>id1</B>, <B>id2</B>, and so on) can be used inside the
handler, just like a method argument. Sometimes you never use the identifier
because the type of the exception gives you enough information to deal with the
exception, but the identifier must still be there.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I17'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I18>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The handlers must appear directly after
the try block. If an exception is thrown, the exception handling mechanism goes
hunting for the first handler with an argument that matches the type of the
exception. Then it enters that catch clause, and the exception is considered
handled. The search for handlers stops once the catch clause is finished. Only
the matching catch clause executes; it’s not like a <B>switch</B>
statement in which you need a <B>break</B> after each <B>case</B> to prevent the
remaining ones from executing.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I18'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I19>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Note that, within the try block, a number
of different method calls might generate the same exception, but you need only
one handler.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I19'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I20>
</FONT><BR></P></DIV>
<A NAME="Heading337"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
Termination vs.
resumption<BR><A NAME="Index1066"></A><A NAME="Index1067"></A><A NAME="Index1068"></A></H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There are two basic models in exception
handling theory. In <I>termination</I> (which is what Java and C++ support), you
assume the error is so critical that there’s no way to get back to where
the exception occurred. Whoever threw the exception decided that there was no
way to salvage the situation, and they don’t <I>want</I> to come back.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I20'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I21>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The alternative is called
<I>resumption</I>. It means that the exception handler is expected to do
something to rectify the situation, and then the faulting method is retried,
presuming success the second time. If you want resumption, it means you still
hope to continue execution after the exception is handled. In this case, your
exception is more like a method call—which is how you should set up
situations in Java in which you want resumption-like behavior. (That is,
don’t throw an exception; call a method that fixes the problem.)
Alternatively, place your <B>try</B> block inside a <B>while</B> loop that keeps
reentering the <B>try</B> block until the result is satisfactory.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I21'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I22>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Historically, programmers using operating
systems that supported resumptive exception handling eventually ended up using
termination-like code and skipping resumption. So although resumption sounds
attractive at first, it isn’t quite so useful in practice. The dominant
reason is probably the <A NAME="Index1069"></A><I>coupling </I>that results:
your handler must often be aware of where the exception is thrown from and
contain nongeneric code specific to the throwing location. This makes the code
difficult to write and maintain, especially for large systems where the
exception can be generated from many points.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I22'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I23>
</FONT><A NAME="_Toc375545373"></A><A NAME="_Toc481064719"></A><BR></P></DIV>
<A NAME="Heading338"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Creating your own exceptions</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You’re not stuck using the existing
Java <A NAME="Index1070"></A>exceptions. This is important because you’ll
often need to create your own exceptions to denote a special error that your
library is capable of creating, but which was not foreseen when the Java
exception hierarchy was created.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER10_I23'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER10_I24>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To create your own exception class,
you’re forced to inherit from an existing type of exception, preferably
one that is close in meaning to your new exception (this is often not possible,
however). The most trivial way to create a new type of exception is just to let
the compiler create the default constructor for you, so it requires almost no
code at all:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c10:SimpleExceptionDemo.java</font>
<font color=#009900>// Inheriting your own exceptions.</font>
<font color=#0000ff>class</font> SimpleException <font color=#0000ff>extends</font> Exception {}
<font color=#0000ff>public</font> <font color=#0000ff>class</font> SimpleExceptionDemo {
<font color=#0000ff>public</font> <font color=#0000ff>void</font> f() <font color=#0000ff>throws</font> SimpleException {
System.out.println(
<font color=#004488>"Throwing SimpleException from f()"</font>);
<font color=#0000ff>throw</font> <font color=#0000ff>new</font> SimpleException ();
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
SimpleExceptionDemo sed =
<font color=#0000ff>new</font> SimpleExceptionDemo();
<font color=#0000ff>try</font> {
sed.f();
} <font color=#0000ff>catch</font>(SimpleException e) {
System.err.println(<font color=#004488>"Caught it!"</font>);
}
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When the compiler creates the default
constructor, it which automatically (and invisibly) calls the base-class default
constructor. Of course, in this case you don’t get a
<B>SimpleException(String)</B> constructor, but in practice that isn’t
used much. As you’ll see, the most important thing about an exception is
the class name, so most of the time an exception like the one shown above is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -