⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tij0051.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<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="tij0050.html">Prev</a> | <a href="tij0052.html">Next</a>
</td>
</tr></table>
<hr>

<H2 ALIGN=LEFT>
Cleanup:
finalization and 
<P>garbage
collection
</H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Programmers
know about the importance of initialization, but often forget the importance of
cleanup. After all, who needs to clean up an 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>int</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">?
But with libraries, simply &#8220;letting go&#8221; of an object once
you&#8217;re done with it is not always safe. Of course, Java has the <A NAME="Index294"></A>garbage
collector to reclaim the memory of objects that are no longer used. Now
consider a very special and unusual case. Suppose your object allocates
&#8220;special&#8221; memory without using <A NAME="Index295"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>new</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The garbage collector knows only how to release memory allocated 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>with</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>new</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
so it won&#8217;t know how to release the object&#8217;s &#8220;special&#8221;
memory. To handle this case, Java provides a method called <A NAME="Index296"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that you can define for your class. Here&#8217;s how it&#8217;s 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>supposed</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to work. When the garbage collector is ready to release the storage used for
your object, it will first call 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and only on the next garbage-collection pass will it reclaim the object&#8217;s
memory. So if you choose to use 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
it gives you the ability to perform some important cleanup 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>at
the time of garbage collection
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
is a potential programming pitfall because some programmers, especially C++
programmers, might initially mistake 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for the <A NAME="Index297"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>destructor</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in C++, which is a function that is always called when an object is destroyed.
But it is important to distinguish between C++ and Java here, because in C++ 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>objects
always get destroyed
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(in a bug-free program), whereas in Java objects do not always get
garbage-collected. Or, put another way:
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Calligraph421 BT" SIZE=4 COLOR="Black">Garbage
collection is not destruction.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you remember this, you will stay out of trouble. What it means is that if there
is some activity that must be performed before you no longer need an object,
you must perform that activity yourself. Java has no destructor or similar
concept, so you must create an ordinary method to perform this cleanup. For
example, suppose in the process of creating your object it draws itself on the
screen. If you don&#8217;t explicitly erase its image from the screen, it might
never get cleaned up. If you put some kind of erasing functionality inside 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
then if an object is garbage-collected, the image will first be removed from
the screen, but if it isn&#8217;t, the image will remain. So a second point to
remember is:
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Calligraph421 BT" SIZE=4 COLOR="Black">Your
objects might not get garbage collected.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
might find that the storage for an object never gets released because your
program never nears the point of running out of storage. If your program
completes and the garbage collector never gets around to releasing the storage
for any of your objects, that storage will be returned to the operating system 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>en
masse
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as the program exits. This is a good thing, because garbage collection has some
overhead, and if you never do it you never incur that expense.
</FONT><a name="_Toc375545282"></a><a name="_Toc408018484"></a><P></DIV>
<A NAME="Heading148"></A><H3 ALIGN=LEFT>
What
is finalize(&#160;) for?
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
might believe at this point that you should not use 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as a general-purpose cleanup method. What good is it?
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">A
third point to remember is:
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Calligraph421 BT" SIZE=4 COLOR="Black">Garbage
collection is only about memory.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">That
is, the sole reason for the existence of the garbage collector is to recover
memory that your program is no longer using. So any activity that is associated
with garbage collection, most notably your 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method, must also be only about memory and its deallocation. 
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Does
this mean that if your object contains other objects 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
should explicitly release those objects? Well, no &#8211; the garbage collector
takes care of the release of all object memory regardless of how the object is
created. It turns out that the need for 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is limited to special cases, in which your object can allocate some storage in
some way other than creating an object. But, you might observe, everything in
Java is an object so how can this be?
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">It
would seem that 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is in place because of the possibility that you&#8217;ll do something C-like by
allocating memory using a mechanism other than the normal one in Java. This can
happen primarily through 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>native
methods
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which are a way to call non-Java code from Java. (Native methods are discussed
in Appendix A.) C and C++ are the only languages currently supported by native
methods, but since they can call subprograms in other languages, you can
effectively call anything. Inside the non-Java code, C&#8217;s 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>malloc(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
family of functions might be called to allocate storage, and unless you call 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>free(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that storage will not be released, causing a memory leak. Of course, 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>free(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is a C and C++ function, so you&#8217;d need call it in a native method inside
your 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">After
reading this, you probably get the idea that you won&#8217;t use 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
much. You&#8217;re correct; it is not the appropriate place for normal cleanup
to occur. So where should normal cleanup be performed?
</FONT><a name="_Toc375545283"></a><a name="_Toc408018485"></a><a name="_Toc312373857"></a><P></DIV>
<A NAME="Heading149"></A><H3 ALIGN=LEFT>
You
must perform cleanup
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">To
clean up an object, the user of that object must call a <A NAME="Index298"></A>cleanup
method at the point the cleanup is desired. This sounds pretty straightforward,
but it collides a bit with the C++ concept of the <A NAME="Index299"></A>destructor.
In C++, all objects are destroyed. Or rather, all objects 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>should
be
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
destroyed. If the C++ object is created as a local, i.e. on the stack (not
possible in Java), then the destruction happens at the closing curly brace of
the scope in which the object was created. If the object was created using 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>new</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(like in Java) the destructor is called when the programmer calls the C++
operator 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>delete</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(which doesn&#8217;t exist in Java). If the programmer forgets, the destructor
is never called and you have a memory leak, plus the other parts of the object
never get cleaned up.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
contrast, Java doesn&#8217;t allow you to create local objects &#8211; you must
always use 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>new</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
But in Java, there&#8217;s no &#8220;delete&#8221; to call for releasing the
object since the garbage collector releases the storage for you. So from a
simplistic standpoint you could say that because of garbage collection, Java
has no destructor. You&#8217;ll see as this book progresses, however, that the
presence of a <A NAME="Index300"></A>garbage
collector does not remove the need or utility of destructors. (And you should
never call <A NAME="Index301"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
directly, so that&#8217;s not an appropriate avenue for a solution.) If you
want some kind of cleanup performed other than storage release you must 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>still</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
call a method in Java, which is the equivalent of a C++ destructor without the
convenience.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">One
of the things 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
can be useful for is observing the process of garbage collection. The following
example shows you what&#8217;s going on and summarizes the previous
descriptions of garbage collection:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: Garbage.java</font>
<font color="#009900">// Demonstration of the garbage</font>
<font color="#009900">// collector and finalization</font>

<font color="#0000ff">class</font> Chair {
  <font color="#0000ff">static</font> <font color="#0000ff">boolean</font> gcrun = <font color="#0000ff">false</font>;
  <font color="#0000ff">static</font> <font color="#0000ff">boolean</font> f = <font color="#0000ff">false</font>;
  <font color="#0000ff">static</font> <font color="#0000ff">int</font> created = 0;
  <font color="#0000ff">static</font> <font color="#0000ff">int</font> finalized = 0;
  <font color="#0000ff">int</font> i;
  Chair() {
    i = ++created;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -