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

📄 tij306.htm

📁 这也是我们java老师给我们的thinking in java的一些资料
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<p>This is internal and you can&#146;t write these expressions and get the compiler to accept them, but it gives you an idea of what&#146;s happening. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_683" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Suppose you&#146;re inside a method and you&#146;d like to get the reference to the current object. Since that reference is passed <i>secretly</i> by the compiler, there&#146;s no identifier for it. However, for this purpose there&#146;s a keyword: <b>this</b>. The <b>this</b> keyword&#151;which can be used only inside a method&#151;produces the reference to the object the method has been called for. You can treat this reference just like any other object reference. Keep in mind that if you&#146;re calling a method of your class from within another method of your class, you don&#146;t need to use <b>this</b>. You simply call the method. The current <b>this</b> reference is automatically used for the other method. Thus you can say: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_684" title="Send BackTalk Comment">Feedback</a></font><br></p>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>class</font> Apricot {
  <font color=#0000ff>void</font> pick() { <font color=#009900>/* ... */</font> }
  <font color=#0000ff>void</font> pit() { pick(); <font color=#009900>/* ... */</font> }
}</PRE></FONT></BLOCKQUOTE><p><br></p>
<p>Inside <b>pit(&#160;)</b>, you <i>could</i> say <b>this.pick(&#160;)</b> but there&#146;s no need to.<sup><a name="fnB20" href="#fn20">[20]</a></sup> The compiler does it for you automatically. The <b>this</b> keyword is used only for those special cases in which you need to explicitly use the reference to the current object. For example, it&#146;s often used in <b>return</b> statements when you want to return the reference to the current object: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_685" title="Send BackTalk Comment">Feedback</a></font><br></p>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c04:Leaf.java</font>
<font color=#009900>// Simple use of the "this" keyword.</font>
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Leaf {
  <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
  <font color=#0000ff>int</font> i = 0;
  Leaf increment() {
    i++;
    <font color=#0000ff>return</font> <font color=#0000ff>this</font>;
  }
  <font color=#0000ff>void</font> print() {
    System.out.println(<font color=#004488>"i = "</font> + i);
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Leaf x = <font color=#0000ff>new</font> Leaf();
    x.increment().increment().increment().print();
    monitor.expect(<font color=#0000ff>new</font> String[] {
      <font color=#004488>"i = 3"</font>
    });
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>Because <b>increment(&#160;)</b> returns the reference to the current object via the <b>this</b> keyword, multiple operations can easily be performed on the same object. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_686" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h4>
<a name="Heading3828"></a>Calling constructors from constructors<br></h4>
<p><a name="Index349"></a>When you write several constructors for a class, there are times when you&#146;d like to call one constructor from another to avoid duplicating code. You can make such a call by by using the <b>this</b> keyword. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_687" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Normally, when you say <b>this</b>, it is in the sense of &#147;this object&#148; or &#147;the current object,&#148; and by itself it produces the reference to the current object. In a constructor, the <b>this</b> keyword takes on a different meaning when you give it an argument list. It makes an explicit call to the constructor that matches that argument list. Thus you have a straightforward way to call other constructors: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_688" title="Send BackTalk Comment">Feedback</a></font><br></p>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c04:Flower.java</font>
<font color=#009900>// Calling constructors with "this."</font>
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Flower {
  <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
  <font color=#0000ff>int</font> petalCount = 0;
  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();
    monitor.expect(<font color=#0000ff>new</font> String[] {
      <font color=#004488>"Constructor w</font><font color=#004488>/ int arg only, petalCount= 47"</font>,
      <font color=#004488>"String &amp; int args"</font>,
      <font color=#004488>"default constructor (no args)"</font>,
      <font color=#004488>"petalCount = 47 s = hi"</font>
    });
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>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&#146;ll get a compiler error message. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_689" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>This example also shows another way you&#146;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&#146;s an ambiguity. You can resolve it using <b>this.s</b>, to say that you&#146;re referring to the member data. You&#146;ll often see this form used in Java code, and it&#146;s used in numerous places in this book. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_690" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>In <b>print(&#160;)</b> you can see that the compiler won&#146;t let you call a constructor from inside any method other than a constructor. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_691" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h4>
<a name="Heading3880"></a>The meaning of <b>static</b><br></h4>
<p><a name="Index350"></a>With the <b>this </b>keyword in mind, you can more fully understand what it means to make a <a name="Index351"></a><a name="Index352"></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<sup><a name="fnB21" href="#fn21">[21]</a></sup> (although the reverse is possible), and you can call a <b>static</b> method for the class itself, without any object. In fact, that&#146;s primarily what a <b>static</b> method is for. It&#146;s as if you&#146;re creating the equivalent of a global function (from C). However, 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 size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_692" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>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&#146;t send a message to an object, since there&#146;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 &#147;proper OOP&#148; should be left to the theoreticians. Indeed, even Smalltalk has the equivalent in its &#147;class methods.&#148;<a name="Index353"></a><i> </i><font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_693" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h2>
<a name="_Toc375545281"></a><a name="_Toc24775607"></a><a name="Heading3884"></a>Cleanup:
finalization and <br>garbage collection</h2>
<p>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 &#147;letting go&#148; of an object once you&#146;re done with it is not always safe. Of course, Java has the garbage collector to reclaim the memory of objects that are no longer used. Now consider an unusual case: suppose your object allocates &#147;special&#148; memory without using <a name="Index354"></a><a name="Index355"></a><b>new</b>. The garbage collector only knows how to release memory allocated <i>with</i> <b>new</b>, so it won&#146;t know how to release the object&#146;s &#147;special&#148; memory. To handle this case, Java provides a method called <a name="Index356"></a><b>finalize(&#160;)</b> that you can define for your class. Here&#146;s how it&#146;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&#146;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 size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_694" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>This is a potential programming pitfall because some programmers, especially C++ programmers, might initially mistake <b>finalize(&#160;)</b> for the <a name="Index357"></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 size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_695" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p class="makeapoint"><i>1. Your objects might not get garbage collected.</i><br></p>
<p class="makeapoint"><i>2. Garbage collection is not destruction.</i><br></p>
<p>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 that in the process of creating your object, it draws itself on the screen. If you don&#146;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 and <b>finalize(&#160;)</b> is called (there&#146;s no guarantee this will happen), then the image will first be removed from the screen, but if it isn&#146;t, the image will remain. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_696" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>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 size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_697" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h3>
<a name="_Toc375545282"></a><a name="_Toc24775608"></a><a name="Heading3891"></a>What
is <b>finalize(&#160;)</b> for?</h3>
<p>So, if you should not use <b>finalize(&#160;)</b> as a general-purpose cleanup method, what good is it? <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_698" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>A third point to remember is:<br></p>
<p class="makeapoint"><i>3. Garbage collection is only about memory.</i><br></p>
<p>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 size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_699" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Does this mean that if your object contains other objects, <b>finalize(&#160;)</b> should explicitly release those objects? Well, no&#151;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 size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_700" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>It would seem that <b>finalize(&#160;)</b> is in place because of the possibility that you&#146;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 covered in Appendix B in the electronic 2<sup>nd</sup> edition of this book, available on this book&#146;s CD ROM and at www.BruceEckel.com.) 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&#146;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&#146;d need to call it in a native method inside your <b>finalize(&#160;)</b>. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_701" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>After reading this, you probably get the idea that you won&#146;t use <b>finalize(&#160;)</b> much.<sup><a name="fnB22" href="#fn22">[22]</a></sup> You&#146;re correct; it is not the appropriate place for normal cleanup to occur. So where should normal cleanup be performed? <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_702" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h3>
<a name="_Toc312373857"></a><a name="_Toc375545283"></a><a name="_Toc24775609"></a><a name="Heading3900"></a>You
must perform cleanup</h3>
<p>To clean up an object, the user of that object must call 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 destructor. In C++, all objects are destroyed. Or rather, all objects <a name="Index358"></a><a name="Index359"></a><i>should be</i> destroyed. If the C++ object is created as a local (i.e., on the stack&#151;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&#146;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, and is one of the compelling reasons to move from C++ to Java. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_703" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>In contrast, Java doesn&#146;t allow you to create local objects&#151;you must always use <b>new</b>. But in Java, there&#146;s no &#147;delete&#148; to call to release the object, because 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&#146;ll see as this book progresses, however, that the presence of a garbage collector does not remove the need for or utility of destructors. (And you should never call <a name="Index360"></a><a name="Index361"></a><b>finalize(&#160;)</b> directly, so that&#146;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. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_704" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Remember that neither garbage collection nor finalization is guaranteed. If the JVM isn&#146;t close to running out of memory, then it might not waste time recovering memory through garbage collection. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_714" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h3>
<a name="_Toc24775610"></a><a name="Heading3904"></a>The termination
condition<br></h3>
<p><a name="Index362"></a><a name="Index363"></a>In general, you can&#146;t rely on <b>finalize(&#160;) </b>being called, and you must create separate &#147;cleanup&#148; methods and call them explicitly. So it appears that <b>finalize(&#160;)</b> is only useful for obscure memory cleanup that most programmers will never use. However, there is a very interesting use of <b>finalize(&#160;)</b> that does not rely on it being called every time. This is the verification of the <i>termination condition</i><sup><a name="fnB23" href="#fn23">[23]</a></sup> of an object. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_715" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>At the point that you&#146;re no longer interested in an object&#151;when it&#146;s ready to be cleaned up&#151;that object should be in a state whereby its memory can be safely released. For example, if the object represents an open file, that file should be closed by the programmer before the object is garbage collected. If any portions of the object are not properly cleaned up, then you have a bug in your program that could be very difficult to find. The value of <b>finalize(&#160;)</b> is that it can be used to eventually discover this condition, even if it isn&#146;t always called. If one of the finalizations happens to reveal the bug, then you discover the problem, which is all you really care about. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap04_716" title="Send BackTalk

⌨️ 快捷键说明

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