📄 tij0102.html
字号:
<font color="#009900">// Finally Guarantees cleanup</font>
<font color="#0000ff">class</font> Switch2 {
<font color="#0000ff">boolean</font> state = <font color="#0000ff">false</font>;
<font color="#0000ff">boolean</font> read() { <font color="#0000ff">return</font> state; }
<font color="#0000ff">void</font> on() { state = <font color="#0000ff">true</font>; }
<font color="#0000ff">void</font> off() { state = <font color="#0000ff">false</font>; }
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> WithFinally {
<font color="#0000ff">static</font> Switch2 sw = <font color="#0000ff">new</font> Switch2();
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
<font color="#0000ff">try</font> {
sw.on();
<font color="#009900">// Code that can throw exceptions...</font>
} <font color="#0000ff">catch</font>(NullPointerException e) {
System.out.println("NullPointerException");
} <font color="#0000ff">catch</font>(IllegalArgumentException e) {
System.out.println("IOException");
} <font color="#0000ff">finally</font> {
sw.off();
}
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Here
the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>sw.off( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
has been moved to just one place, where it’s guaranteed to run no matter
what happens.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Even
in cases in which the exception is not caught in the current set of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>catch</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
clauses,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finally</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
will be executed before the exception-handling mechanism continues its search
for a handler at the next higher level:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: AlwaysFinally.java</font>
<font color="#009900">// Finally is always executed</font>
<font color="#0000ff">class</font> Ex <font color="#0000ff">extends</font> Exception {}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> AlwaysFinally {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
System.out.println(
"Entering first <font color="#0000ff">try</font> block");
<font color="#0000ff">try</font> {
System.out.println(
"Entering second <font color="#0000ff">try</font> block");
<font color="#0000ff">try</font> {
<font color="#0000ff">throw</font> <font color="#0000ff">new</font> Ex();
} <font color="#0000ff">finally</font> {
System.out.println(
"<font color="#0000ff">finally</font> in 2nd <font color="#0000ff">try</font> block");
}
} <font color="#0000ff">catch</font>(Ex e) {
System.out.println(
"Caught Ex in first <font color="#0000ff">try</font> block");
} <font color="#0000ff">finally</font> {
System.out.println(
"<font color="#0000ff">finally</font> in 1st <font color="#0000ff">try</font> block");
}
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
output for this program shows you what happens:
</FONT><P></DIV>
<font color="#990000"><PRE>Entering first <font color="#0000ff">try</font> block
Entering second <font color="#0000ff">try</font> block
<font color="#0000ff">finally</font> in 2nd <font color="#0000ff">try</font> block
Caught Ex in first <font color="#0000ff">try</font> block
<font color="#0000ff">finally</font> in 1st <font color="#0000ff">try</font> block </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finally</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
statement will also be executed in situations in which
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>break</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>continue</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
statements are involved. Note that, along with the labeled
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>break</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and labeled
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>continue</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finally</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
eliminates the need for a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>goto
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">statement
in Java.
</FONT><a name="_Toc408018603"></a><P></DIV>
<A NAME="Heading297"></A><H3 ALIGN=LEFT>
Pitfall:
the lost exception
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
general, Java’s exception implementation is quite outstanding, but
unfortunately there’s a flaw. Although exceptions are an indication of a
crisis in your program and should never be ignored, it’s possible for an
exception to simply be <A NAME="Index957"></A>lost.
This happens with a particular configuration using a <A NAME="Index958"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finally</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
clause:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: LostMessage.java</font>
<font color="#009900">// How an exception can be lost</font>
<font color="#0000ff">class</font> VeryImportantException <font color="#0000ff">extends</font> Exception {
<font color="#0000ff">public</font> String toString() {
<font color="#0000ff">return</font> "A very important exception!";
}
}
<font color="#0000ff">class</font> HoHumException <font color="#0000ff">extends</font> Exception {
<font color="#0000ff">public</font> String toString() {
<font color="#0000ff">return</font> "A trivial exception";
}
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> LostMessage {
<font color="#0000ff">void</font> f() <font color="#0000ff">throws</font> VeryImportantException {
<font color="#0000ff">throw</font> <font color="#0000ff">new</font> VeryImportantException();
}
<font color="#0000ff">void</font> dispose() <font color="#0000ff">throws</font> HoHumException {
<font color="#0000ff">throw</font> <font color="#0000ff">new</font> HoHumException();
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args)
<font color="#0000ff">throws</font> Exception {
LostMessage lm = <font color="#0000ff">new</font> LostMessage();
<font color="#0000ff">try</font> {
lm.f();
} <font color="#0000ff">finally</font> {
lm.dispose();
}
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
output is:
</FONT><P></DIV>
<font color="#990000"><PRE>A trivial exception
at LostMessage.dispose(LostMessage.java:21)
at LostMessage.main(LostMessage.java:29) </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can see that there’s no evidence of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>VeryImportantException</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which is simply replaced by the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>HoHumException</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finally</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
clause. This is a rather serious pitfall, since it means that an exception can
be completely lost, and in a far more subtle and difficult-to-detect fashion
than the example above. In contrast, C++ treats the situation in which a second
exception is thrown before the first one is handled as a dire programming
error. Perhaps a future version of Java will repair the problem. (The above
results were produced with Java 1.1.<A NAME="Index959"></A>)</FONT><a name="_Toc305593300"></a><a name="_Toc305628772"></a><a name="_Toc312374122"></a><a name="_Toc375545376"></a><a name="_Toc408018604"></a><P></DIV>
<HR><DIV ALIGN=LEFT><A NAME="fn44" HREF="#fnB44">[44]</A><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
C++ exception handling does not have the
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><B>finally</B></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
clause because it relies on destructors to accomplish this sort of cleanup.
</FONT><P></DIV><DIV ALIGN=LEFT><A NAME="fn45" HREF="#fnB45">[45]</A><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
A destructor is a function that’s always called when an object becomes
unused. You always know exactly where and when the destructor gets called. C++
has automatic destructor calls, but Delphi’s Object Pascal versions 1 and
2 do not (which changes the meaning and use of the concept of a destructor for
that language).
</FONT><P></DIV>
<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0101.html">Prev</a> | <a href="tij0103.html">Next</a>
</div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -