📄 tij0102.html
字号:
<html><body>
<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0101.html">Prev</a> | <a href="tij0103.html">Next</a>
</td>
</tr></table>
<hr>
<H2 ALIGN=LEFT>
Performing
cleanup
<P>with
finally
</H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">There’s
often some piece of code that you want to execute whether or not an exception
occurs in a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>try</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
block. This usually pertains to some operation other than memory recovery
(since that’s taken care of by the garbage collector). To achieve this
effect, you use a <A NAME="Index951"></A><A NAME="Index952"></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><A NAME="fnB44" HREF="#fn44">[44]</A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
at the end of all the exception handlers. The full picture of an
exception-handling section is thus:
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>try</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
{
</FONT><P><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
// The guarded region:
</FONT><P><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
// Dangerous stuff that might throw A, B, or C
</FONT><P><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">}
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>catch
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(A
a1) {
</FONT><P><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
// Handle A
</FONT><P><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">}
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>catch</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(B b1) {
</FONT><P><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
// Handle B
</FONT><P><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">}
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>catch</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(C c1) {
</FONT><P><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
// Handle C
</FONT><P><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">
{
</FONT><P><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
// Stuff that happens every time
</FONT><P><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">}</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">To
demonstrate that 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 always runs, try this program:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: FinallyWorks.java</font>
<font color="#009900">// The finally clause is always executed</font>
<font color="#0000ff">public</font> <font color="#0000ff">class</font> FinallyWorks {
<font color="#0000ff">static</font> <font color="#0000ff">int</font> count = 0;
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
<font color="#0000ff">while</font>(<font color="#0000ff">true</font>) {
<font color="#0000ff">try</font> {
<font color="#009900">// post-increment is zero first time:</font>
<font color="#0000ff">if</font>(count++ == 0)
<font color="#0000ff">throw</font> <font color="#0000ff">new</font> Exception();
System.out.println("No exception");
} <font color="#0000ff">catch</font>(Exception e) {
System.out.println("Exception thrown");
} <font color="#0000ff">finally</font> {
System.out.println("in <font color="#0000ff">finally</font> clause");
<font color="#0000ff">if</font>(count == 2) <font color="#0000ff">break</font>; <font color="#009900">// out of "while"</font>
}
}
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
program also gives a hint for how you can deal with the fact that exceptions in
Java (like exceptions in C++) do not allow you to resume back to where the
exception was thrown, as discussed earlier. If you place your
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>try</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
block in a loop, you can establish a condition that must be met before you
continue the program. You can also add a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
counter or some other device to allow the loop to try several different
approaches before giving up. This way you can build a greater level of
robustness into your programs.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
output is:
</FONT><P></DIV>
<font color="#990000"><PRE>Exception thrown
in <font color="#0000ff">finally</font> clause
No exception
in <font color="#0000ff">finally</font> clause </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Whether
an exception is thrown or not, 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 is always executed.
</FONT><a name="_Toc375545375"></a><a name="_Toc408018602"></a><P></DIV>
<A NAME="Heading296"></A><H3 ALIGN=LEFT>
What’s
finally for?
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
a language without garbage collection
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>and</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
without automatic <A NAME="Index953"></A>destructor
calls,
</FONT><A NAME="fnB45" HREF="#fn45">[45]</A><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">
is important because it allows the programmer to guarantee the release of
memory regardless of what happens in the <A NAME="Index954"></A><A NAME="Index955"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>try</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
block. But Java has garbage collection, so releasing memory is virtually never
a problem. Also, it has no destructors to call. So when do you need to use <A NAME="Index956"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finally</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in Java?
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finally</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is necessary when you need to set something
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>other</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
than memory back to its original state. This is usually something like an open
file or network connection, something you’ve drawn on the screen or even
a switch in the outside world, as modeled in the following example:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: OnOffSwitch.java</font>
<font color="#009900">// Why use finally?</font>
<font color="#0000ff">class</font> Switch {
<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> OnOffSwitch {
<font color="#0000ff">static</font> Switch sw = <font color="#0000ff">new</font> Switch();
<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>
sw.off();
} <font color="#0000ff">catch</font>(NullPointerException e) {
System.out.println("NullPointerException");
sw.off();
} <font color="#0000ff">catch</font>(IllegalArgumentException e) {
System.out.println("IOException");
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">The
goal here is to make sure that the switch is off when
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is completed, so
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>sw.off( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is placed at the end of the try block and at the end of each exception handler.
But it’s possible that an exception could be thrown that isn’t
caught here, so
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>sw.off( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">would
be missed. However, with
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finally</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
you can place the closure code from a try block in just one place:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: WithFinally.java</font>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -