📄 chap04.htm
字号:
the class itself, without any object. In fact, that’s primarily what a
<B>static</B> method is for. It’s as if you’re creating the
equivalent of a global function (from C). Except global functions are not
permitted in Java, and putting the <B>static</B> method inside a class allows it
access to other <B>static </B>methods and to <B>static</B> fields.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I45'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I46>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Some people argue that <B>static</B>
methods are not object-oriented since they do have the semantics of a global
function; with a <B>static</B> method you don’t send a message to an
object, since there’s no <B>this</B>. This is probably a fair argument,
and if you find yourself using a <I>lot</I> of static methods you should
probably rethink your strategy. However, <B>static</B>s are pragmatic and there
are times when you genuinely need them, so whether or not they are “proper
OOP” should be left to the theoreticians. Indeed, even
<A NAME="Index411"></A>Smalltalk has the equivalent in its “class
methods.”<I>
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I46'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I47>
</I></FONT><A NAME="_Toc375545281"></A><A NAME="_Toc481064576"></A><BR></P></DIV>
<A NAME="Heading173"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Cleanup: finalization and <BR>garbage collection</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Programmers know about the importance of
initialization, but often forget the importance of cleanup. After all, who needs
to clean up an <B>int</B>? But with libraries, simply “letting go”
of an object once you’re done with it is not always safe. Of course, Java
has the <A NAME="Index412"></A>garbage collector to reclaim the memory of
objects that are no longer used. Now consider a very unusual case. Suppose your
object allocates “special” memory without using
<A NAME="Index413"></A><B>new</B>. The garbage collector knows only how to
release memory allocated <I>with</I> <B>new</B>, so it won’t know how to
release the object’s “special” memory. To handle this case,
Java provides a method called <A NAME="Index414"></A><B>finalize( )</B>
that you can define for your class. Here’s how it’s <I>supposed</I>
to work. When the garbage collector is ready to release the storage used for
your object, it will first call <B>finalize( )</B>, and only on the next
garbage-collection pass will it reclaim the object’s memory. So if you
choose to use <B>finalize( )</B>, it gives you the ability to perform some
important cleanup <I>at the time of garbage collection</I>.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I47'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I48>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This is a potential programming pitfall
because some programmers, especially C++ programmers, might initially mistake
<B>finalize( )</B> for the <A NAME="Index415"></A><I>destructor</I> 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++ <I>objects
always get destroyed</I> (in a bug-free program), whereas in Java objects do not
always get garbage-collected. Or, put another way:
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I48'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I49>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia" SIZE=4>Garbage collection is not
destruction.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">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’t
explicitly erase its image from the screen, it might never get cleaned up. If
you put some kind of erasing functionality inside <B>finalize( )</B>, then
if an object is garbage-collected, the image will first be removed from the
screen, but if it isn’t, the image will remain. So a second point to
remember is:
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I49'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I50>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia" SIZE=4>Your objects might not get
garbage-collected.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">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 <I>en masse</I> 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.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I50'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I51>
</FONT><A NAME="_Toc375545282"></A><A NAME="_Toc481064577"></A><BR></P></DIV>
<A NAME="Heading174"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
What is finalize( ) for?</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You might believe at this point that you
should not use <B>finalize( )</B> as a general-purpose cleanup method. What
good is it?
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I51'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I52>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A third point to remember
is:</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia" SIZE=4>Garbage collection is only about
memory.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">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 <B>finalize( )</B> method, must also be only about memory and
its deallocation.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I52'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I53>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Does this mean that if your object
contains other objects <B>finalize( )</B> should explicitly release those
objects? Well, no—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 <B>finalize( )</B> 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?
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I53'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I54>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It would seem that
<B>finalize( )</B> is in place because of the possibility that you’ll
do something C-like by allocating memory using a mechanism other than the normal
one in Java. This can happen primarily through <I>native methods</I>, which are
a way to call non-Java code from Java. (Native methods are discussed in Appendix
B.) 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’s <B>malloc( )</B> family of
functions might be called to allocate storage, and unless you call
<B>free( )</B> that storage will not be released, causing a memory leak. Of
course, <B>free( )</B> is a C and C++ function, so you’d need to call
it in a native method inside your <B>finalize( )</B>.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I54'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I55>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">After reading this, you probably get the
idea that you won’t use <B>finalize( )</B> much. You’re
correct; it is not the appropriate place for normal cleanup to occur. So where
should normal cleanup be performed?
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I55'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I56>
</FONT><A NAME="_Toc312373857"></A><A NAME="_Toc375545283"></A><A NAME="_Toc481064578"></A><BR></P></DIV>
<A NAME="Heading175"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
You must perform cleanup</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To clean up an object, the user of that
object must call a <A NAME="Index416"></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="Index417"></A>destructor. In C++, all
objects are destroyed. Or rather, all objects <I>should be</I> 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 <B>new</B> (like
in Java) the destructor is called when the programmer calls the C++ operator
<B>delete</B> (which doesn’t exist in Java). If the C++ programmer forgets
to call <B>delete</B>, the destructor is never called and you have a memory
leak, plus the other parts of the object never get cleaned up. This kind of bug
can be very difficult to track down.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I56'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I57>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In contrast, Java doesn’t allow you
to create local objects—you must always use <B>new</B>. But in Java,
there’s no “delete” to call to release 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’ll see as this book progresses, however, that the presence of a
<A NAME="Index418"></A>garbage collector does not remove the need for or utility
of destructors. (And you should never call
<A NAME="Index419"></A><B>finalize( )</B> directly, so that’s not an
appropriate avenue for a solution.) If you want some kind of cleanup performed
other than storage release you must <I>still</I> explicitly call an appropriate
method in Java, which is the equivalent of a C++ destructor without the
convenience.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER4_I57'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER4_I58>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">One of the things <B>finalize( )</B>
can be useful for is observing the process of garbage collection. The following
example shows you what’s going on and summarizes the previous descriptions
of garbage collection:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c04: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;
<font color=#0000ff>if</font>(created == 47)
System.out.println(<font color=#004488>"Created 47"</font>);
}
<font color=#0000ff>public</font> <font color=#0000ff>void</font> finalize() {
<font color=#0000ff>if</font>(!gcrun) {
<font color=#009900>// The first time finalize() is called:</font>
gcrun = <font color=#0000ff>true</font>;
System.out.println(
<font color=#004488>"Beginning to finalize after "</font> +
created + <font color=#004488>" Chairs have been created"</font>);
}
<font color=#
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -