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

📄 appenda.htm

📁 Thinking in Java, 2nd edition
💻 HTM
📖 第 1 页 / 共 5 页
字号:
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To know for sure what those other
operations are, you need to understand exactly what <B>Object.clone(&#160;)</B>
buys you. In particular, does it automatically clone the destination of all the
references? The following example tests this:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixa:Snake.java</font>
<font color=#009900>// Tests cloning to see if destination</font>
<font color=#009900>// of references are also cloned.</font>

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Snake <font color=#0000ff>implements</font> Cloneable {
  <font color=#0000ff>private</font> Snake next;
  <font color=#0000ff>private</font> <font color=#0000ff>char</font> c;
  <font color=#009900>// Value of i == number of segments</font>
  Snake(<font color=#0000ff>int</font> i, <font color=#0000ff>char</font> x) {
    c = x;
    <font color=#0000ff>if</font>(--i &gt; 0)
      next = <font color=#0000ff>new</font> Snake(i, (<font color=#0000ff>char</font>)(x + 1));
  }
  <font color=#0000ff>void</font> increment() {
    c++;
    <font color=#0000ff>if</font>(next != <font color=#0000ff>null</font>)
      next.increment();
  }
  <font color=#0000ff>public</font> String toString() {
    String s = <font color=#004488>":"</font> + c;
    <font color=#0000ff>if</font>(next != <font color=#0000ff>null</font>)
      s += next.toString();
    <font color=#0000ff>return</font> s;
  }
  <font color=#0000ff>public</font> Object clone() {
    Object o = <font color=#0000ff>null</font>;
    <font color=#0000ff>try</font> {
      o = <font color=#0000ff>super</font>.clone();
    } <font color=#0000ff>catch</font>(CloneNotSupportedException e) {
      System.err.println(<font color=#004488>"Snake can't clone"</font>);
    }
    <font color=#0000ff>return</font> o;
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Snake s = <font color=#0000ff>new</font> Snake(5, 'a');
    System.out.println(<font color=#004488>"s = "</font> + s);
    Snake s2 = (Snake)s.clone();
    System.out.println(<font color=#004488>"s2 = "</font> + s2);
    s.increment();
    System.out.println(
      <font color=#004488>"after s.increment, s2 = "</font> + s2);
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A <B>Snake</B> is made up of a bunch of
segments, each of type <B>Snake</B>. Thus, it&#8217;s a singly linked list. The
segments are created recursively, decrementing the first constructor argument
for each segment until zero is reached. To give each segment a unique tag, the
second argument, a <B>char</B>, is incremented for each recursive constructor
call. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I26' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXA_I27>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>increment(&#160;)</B> method
recursively increments each tag so you can see the change, and the
<B>toString(&#160;)</B> recursively prints each tag. The output
is:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>s = :a:b:c:d:e
s2 = :a:b:c:d:e
after s.increment, s2 = :a:c:d:e:f</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This means that only the first segment is
duplicated by <B>Object.clone(&#160;)</B>, therefore it does a
<A NAME="Index2247"></A>shallow copy. If you want the whole snake to be
duplicated&#8212;a <A NAME="Index2248"></A>deep copy&#8212;you must perform the
additional operations inside your overridden <B>clone(&#160;)</B>.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I27' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXA_I28>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You&#8217;ll typically call
<B>super.clone(&#160;)</B> in any class derived from a cloneable class to make
sure that all of the base-class operations (including
<B>Object.clone(&#160;)</B>) take place. This is followed by an explicit call to
<B>clone(&#160;) </B>for every reference in your object; otherwise those
references will be aliased to those of the original object. It&#8217;s analogous
to the way constructors are called&#8212;base-class constructor first, then the
next-derived constructor, and so on to the most-derived constructor. The
difference is that <B>clone(&#160;)</B> is not a constructor, so there&#8217;s
nothing to make it happen automatically. You must make sure to do it yourself.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I28' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXA_I29>
</FONT><A NAME="_Toc481064932"></A><BR></P></DIV>
<A NAME="Heading610"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Cloning a composed
object<BR><A NAME="Index2249"></A><A NAME="Index2250"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There&#8217;s a problem you&#8217;ll
encounter when trying to deep copy a composed object. You must assume that the
<B>clone(&#160;)</B> method in the member objects will in turn perform a deep
copy on <I>their</I> references, and so on. This is quite a commitment. It
effectively means that for a deep copy to work you must either control all of
the code in all of the classes, or at least have enough knowledge about all of
the classes involved in the deep copy to know that they are performing their own
deep copy correctly. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I29' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXA_I30>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This example shows what you must do to
accomplish a deep copy when dealing with a composed object:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixa:DeepCopy.java</font>
<font color=#009900>// Cloning a composed object.</font>

<font color=#0000ff>class</font> DepthReading <font color=#0000ff>implements</font> Cloneable {
  <font color=#0000ff>private</font> <font color=#0000ff>double</font> depth;
  <font color=#0000ff>public</font> DepthReading(<font color=#0000ff>double</font> depth) { 
    <font color=#0000ff>this</font>.depth = depth;
  }
  <font color=#0000ff>public</font> Object clone() {
    Object o = <font color=#0000ff>null</font>;
    <font color=#0000ff>try</font> {
      o = <font color=#0000ff>super</font>.clone();
    } <font color=#0000ff>catch</font>(CloneNotSupportedException e) {
      e.printStackTrace(System.err);
    }
    <font color=#0000ff>return</font> o;
  }
}

<font color=#0000ff>class</font> TemperatureReading <font color=#0000ff>implements</font> Cloneable {
  <font color=#0000ff>private</font> <font color=#0000ff>long</font> time;
  <font color=#0000ff>private</font> <font color=#0000ff>double</font> temperature;
  <font color=#0000ff>public</font> TemperatureReading(<font color=#0000ff>double</font> temperature) {
    time = System.currentTimeMillis();
    <font color=#0000ff>this</font>.temperature = temperature;
  }
  <font color=#0000ff>public</font> Object clone() {
    Object o = <font color=#0000ff>null</font>;
    <font color=#0000ff>try</font> {
      o = <font color=#0000ff>super</font>.clone();
    } <font color=#0000ff>catch</font>(CloneNotSupportedException e) {
      e.printStackTrace(System.err);
    }
    <font color=#0000ff>return</font> o;
  }
}

<font color=#0000ff>class</font> OceanReading <font color=#0000ff>implements</font> Cloneable {
  <font color=#0000ff>private</font> DepthReading depth;
  <font color=#0000ff>private</font> TemperatureReading temperature;
  <font color=#0000ff>public</font> OceanReading(<font color=#0000ff>double</font> tdata, <font color=#0000ff>double</font> ddata){
    temperature = <font color=#0000ff>new</font> TemperatureReading(tdata);
    depth = <font color=#0000ff>new</font> DepthReading(ddata);
  }
  <font color=#0000ff>public</font> Object clone() {
    OceanReading o = <font color=#0000ff>null</font>;
    <font color=#0000ff>try</font> {
      o = (OceanReading)<font color=#0000ff>super</font>.clone();
    } <font color=#0000ff>catch</font>(CloneNotSupportedException e) {
      e.printStackTrace(System.err);
    }
    <font color=#009900>// Must clone references:</font>
    o.depth = (DepthReading)o.depth.clone();
    o.temperature = 
      (TemperatureReading)o.temperature.clone();
    <font color=#0000ff>return</font> o; <font color=#009900>// Upcasts back to Object</font>
  }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> DeepCopy {
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    OceanReading reading = 
      <font color=#0000ff>new</font> OceanReading(33.9, 100.5);
    <font color=#009900>// Now clone it:</font>
    OceanReading r = 
      (OceanReading)reading.clone();
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>DepthReading</B> and
<B>TemperatureReading</B> are quite similar; they both contain only primitives.
Therefore, the <B>clone(&#160;)</B> method can be quite simple: it calls
<B>super.clone(&#160;)</B> and returns the result. Note that the
<B>clone(&#160;)</B> code for both classes is identical.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I30' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXA_I31>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>OceanReading</B> is composed of
<B>DepthReading</B> and <B>TemperatureReading</B> objects and so, to produce a
deep copy, its <B>clone(&#160;)</B> must clone the references inside
<B>OceanReading</B>. To accomplish this, the result of
<B>super.clone(&#160;)</B> must be cast to an <B>OceanReading</B> object (so you
can access the <B>depth</B> and <B>temperature</B> references).

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I31' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXA_I32>
</FONT><A NAME="_Toc481064933"></A><BR></P></DIV>
<A NAME="Heading611"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
A deep copy with ArrayList</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Let&#8217;s revisit the
<A NAME="Index2251"></A><A NAME="Index2252"></A><B>ArrayList</B> example from
earlier in this appendix. This time the <B>Int2</B> class is cloneable, so the
<B>ArrayList</B> can be deep copied:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixa:AddingClone.java</font>
<font color=#009900>// You must go through a few gyrations</font>
<font color=#009900>// to add cloning to your own class.</font>
<font color=#0000ff>import</font> java.util.*;

<font color=#0000ff>class</font> Int2 <font color=#0000ff>implements</font> Cloneable {
  <font color=#0000ff>private</font> <font color=#0000ff>int</font> i;
  <font color=#0000ff>public</font> Int2(<font color=#0000ff>int</font> ii) { i = ii; }
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> increment() { i++; }
  <font color=#0000ff>public</font> String toString() {
    <font color=#0000ff>return</font> Integer.toString(i);
  }
  <font color=#0000ff>public</font> Object clone() {
    Object o = <font color=#0000ff>null</font>;
    <font color=#0000ff>try</font> {
      o = <font color=#0000ff>super</font>.clone();
    } <font color=#0000ff>catch</font>(CloneNotSupportedException e) {
      System.err.println(<font color=#004488>"Int2 can't clone"</font>);
    }
    <font color=#0000ff>return</font> o;
  }
}

<font color=#009900>// Once it's cloneable, inheritance</font>
<font color=#009900>// doesn't remove cloneability:</font>
<font color=#0000ff>class</font> Int3 <font color=#0000ff>extends</font> Int2 {
  <font color=#0000ff>private</font> <font color=#0000ff>int</font> j; <font color=#009900>// Automatically duplicated</font>
  <font color=#0000ff>public</font> Int3(<font color=#0000ff>int</font> i) { <font color=#0000ff>super</font>(i); }

⌨️ 快捷键说明

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