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

📄 chapter04.html

📁 java 是一个很好的网络开发环境。由于它是通过解释的方法
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<font color=#009900>// Calling constructors with "this"</font>

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Flower {
  <font color=#0000ff>private</font> <font color=#0000ff>int</font> petalCount = 0;
  <font color=#0000ff>private</font> String s = <font color=#0000ff>new</font> String(<font color=#004488>"null"</font>);
  Flower(<font color=#0000ff>int</font> petals) {
    petalCount = petals;
    System.out.println(
      <font color=#004488>"Constructor w</font><font color=#004488>/ int arg only, petalCount= "</font>
      + petalCount);
  }
  Flower(String ss) {
    System.out.println(
      <font color=#004488>"Constructor w</font><font color=#004488>/ String arg only, s="</font> + ss);
    s = ss;
  }
  Flower(String s, <font color=#0000ff>int</font> petals) {
    <font color=#0000ff>this</font>(petals);
<font color=#009900>//!    this(s); // Can't call two!</font>
    <font color=#0000ff>this</font>.s = s; <font color=#009900>// Another use of "this"</font>
    System.out.println(<font color=#004488>"String &amp; int args"</font>);
  }
  Flower() {
    <font color=#0000ff>this</font>(<font color=#004488>"hi"</font>, 47);
    System.out.println(
      <font color=#004488>"default constructor (no args)"</font>);
  }
  <font color=#0000ff>void</font> print() {
<font color=#009900>//!    this(11); // Not inside non-constructor!</font>
    System.out.println(
      <font color=#004488>"petalCount = "</font> + petalCount + <font color=#004488>" s = "</font>+ s);
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Flower x = <font color=#0000ff>new</font> Flower();
    x.print();
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The constructor <B>Flower(String s,
int petals)</B> shows that, while you can call one constructor using
<B>this</B>, you cannot call two. In addition, the constructor call must be the
first thing you do or you&#8217;ll get a compiler error
message.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This example also shows another way
you&#8217;ll see <B>this</B> used. Since the name of the argument <B>s </B>and
the name of the member data <B>s</B> are the same, there&#8217;s an ambiguity.
You can resolve it by saying <B>this.s</B> to refer to the member data.
You&#8217;ll often see this form used in Java code, and it&#8217;s used in
numerous places in this book.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In <B>print(&#160;)</B> you can see
that the compiler won&#8217;t let you call a constructor from inside any method
other than a constructor.</FONT><BR></P></DIV>
<A NAME="Heading145"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
The meaning of static<BR><A NAME="Index290"></A></H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">With the <B>this </B>keyword in
mind, you can more fully understand what it means to make a
<A NAME="Index291"></A><A NAME="Index292"></A>method <B>static</B>. It means
that there is no <B>this</B> for that particular method. You cannot call
non-<B>static</B> methods from inside <B>static</B>
methods</FONT><A NAME="fnB18" HREF="#fn18">[18]</A><FONT FACE="Georgia">
(although the reverse is possible), and you can call a <B>static</B> method for
the class itself, without any object. In fact, that&#8217;s primarily what a
<B>static</B> method is for. It&#8217;s as if you&#8217;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.</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&#8217;t send a message
to an object, since there&#8217;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
&#8220;proper OOP&#8221; should be left to the theoreticians. Indeed, even
<A NAME="Index293"></A>Smalltalk has the equivalent in its &#8220;class
methods.&#8221;</FONT><A NAME="_Toc375545281"></A><A NAME="_Toc408018483"></A><BR></P></DIV>
<A NAME="Heading146"></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
&#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><B>new</B>. The garbage collector
knows only how to release memory allocated <I>with</I> <B>new</B>, 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><B>finalize(&#160;)</B> that you can define for your
class. Here&#8217;s how it&#8217;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(&#160;)</B>, and only on the next garbage-collection pass will
it reclaim the object&#8217;s memory. So if you choose to use
<B>finalize(&#160;)</B>, it gives you the ability to perform some important
cleanup <I>at the time of garbage collection</I>.</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(&#160;)</B> for the <A NAME="Index297"></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:</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Verdana" 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&#8217;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(&#160;)</B>, 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><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Verdana" 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.</FONT><A NAME="_Toc375545282"></A><A NAME="_Toc408018484"></A><BR></P></DIV>
<A NAME="Heading147"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
What is finalize(&#160;) for?</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You might believe at this point
that you should not use <B>finalize(&#160;)</B> as a general-purpose cleanup
method. What good is it?</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="Verdana" 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(&#160;)</B> method, must also be only about memory and
its deallocation. </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Does this mean that if your object
contains other objects <B>finalize(&#160;)</B> 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 <B>finalize(&#160;)</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?</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It would seem that
<B>finalize(&#160;)</B> 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 <I>native methods</I>, 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 <B>malloc(&#160;)</B> family of
functions might be called to allocate storage, and unless you call
<B>free(&#160;)</B> that storage will not be released, causing a memory leak. Of
course, <B>free(&#160;)</B> is a C and C++ function, so you&#8217;d need call it
in a native method inside your <B>finalize(&#160;)</B>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">After reading this, you probably
get the idea that you won&#8217;t use <B>finalize(&#160;)</B> 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="_Toc312373857"></A><A NAME="_Toc375545283"></A><A NAME="_Toc408018485"></A><BR></P></DIV>
<A NAME="Heading148"></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="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 <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&#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><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In contrast, Java doesn&#8217;t
allow you to create local objects &#8211; you must always use <B>new</B>. 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><B>finalize(&#160;)</B> 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 <I>still</I> call a method in Java, which is
the equivalent of a C++ destructor without the convenience.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">One of the things
<B>finalize(&#160;)</B> 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><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><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;
    <font color=#0000ff>if</font>(created == 47) 
      System.out.println(<font color=#004488>"Created 47"</font>);
  }

⌨️ 快捷键说明

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