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

📄 appenda.htm

📁 Thinking in Java, 2nd edition
💻 HTM
📖 第 1 页 / 共 5 页
字号:
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I16' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXA_I17>
</FONT><BR></P></DIV>
<UL>
<LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Virtually always call
<B>super.clone(&#160;)
</B></FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Make your clone
<B>public</B></FONT></UL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You&#8217;ll
probably want to override <B>clone(&#160;) </B>in any further derived classes,
otherwise your (now <B>public</B>) <B>clone(&#160;)</B> will be used, and that
might not do the right thing (although, since <B>Object.clone(&#160;)</B> makes
a copy of the actual object, it might). The <B>protected</B> trick works only
once&#8212;the first time you inherit from a class that has no cloneability and
you want to make a class that&#8217;s cloneable. In any classes inherited from
your class the <B>clone(&#160;) </B>method is available since it&#8217;s not
possible in Java to reduce the access of a method during derivation. That is,
once a class is cloneable, everything derived from it is cloneable unless you
use provided mechanisms (described later) to &#8220;turn off&#8221; cloning.

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

<backtalk:display ID=TIJ3_APPENDIXA_I18>
</FONT><BR></P></DIV>
<A NAME="Heading607"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
Implementing the Cloneable interface</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There&#8217;s one more thing you need to
do to complete the cloneability of an object: implement the
<A NAME="Index2233"></A><B>Cloneable</B> <B>interface</B>. This
<A NAME="Index2234"></A><B>interface</B> is a bit strange, because it&#8217;s
empty!</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>interface</font> Cloneable {}</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The reason for implementing this empty
<B>interface</B> is obviously not because you are going to upcast to
<B>Cloneable</B> and call one of its methods. The use of <B>interface</B> here
is considered by some to be a &#8220;hack&#8221; because it&#8217;s using a
feature for something other than its original intent. Implementing the
<B>Cloneable</B> <B>interface</B> acts as a kind of a flag, wired into the type
of the class.  
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I18' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXA_I19>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There are two reasons for the existence
of the <B>Cloneable</B> <B>interface</B>. First, you might have an upcast
reference to a base type and not know whether it&#8217;s possible to clone that
object. In this case, you can use the <B>instanceof</B> keyword (described in
Chapter 12) to find out whether the reference is connected to an object that can
be cloned:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>if</font>(myReference <font color=#0000ff>instanceof</font> Cloneable) <font color=#009900>// ...</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The second reason is that mixed into this
design for cloneability was the thought that maybe you didn&#8217;t want all
types of objects to be cloneable. So <B>Object.clone(&#160;)</B> verifies that a
class implements the <B>Cloneable</B> interface. If not, it throws a
<B>CloneNotSupportedException</B> exception. So in general, you&#8217;re forced
to <B>implement Cloneable</B> as part of support for cloning.

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

<backtalk:display ID=TIJ3_APPENDIXA_I20>
</FONT><A NAME="_Toc375545427"></A><A NAME="_Toc481064930"></A><BR></P></DIV>
<A NAME="Heading608"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Successful cloning</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Once you understand the details of
implementing the <B>clone(&#160;)</B> method, you&#8217;re able to create
classes that can be easily duplicated to provide a local copy:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixa:LocalCopy.java</font>
<font color=#009900>// Creating local copies with clone().</font>
<font color=#0000ff>import</font> java.util.*;

<font color=#0000ff>class</font> MyObject <font color=#0000ff>implements</font> Cloneable {
  <font color=#0000ff>int</font> i;
  MyObject(<font color=#0000ff>int</font> ii) { i = ii; }
  <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>"MyObject can't clone"</font>);
    }
    <font color=#0000ff>return</font> o;
  }
  <font color=#0000ff>public</font> String toString() {
    <font color=#0000ff>return</font> Integer.toString(i);
  }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> LocalCopy {
  <font color=#0000ff>static</font> MyObject g(MyObject v) {
    <font color=#009900>// Passing a reference, </font>
    <font color=#009900>// modifies outside object:</font>
    v.i++;
    <font color=#0000ff>return</font> v;
  }
  <font color=#0000ff>static</font> MyObject f(MyObject v) {
    v = (MyObject)v.clone(); <font color=#009900>// Local copy</font>
    v.i++;
    <font color=#0000ff>return</font> v;
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    MyObject a = <font color=#0000ff>new</font> MyObject(11);
    MyObject b = g(a);
    <font color=#009900>// Testing reference equivalence,</font>
    <font color=#009900>// not object equivalence:</font>
    <font color=#0000ff>if</font>(a == b) 
      System.out.println(<font color=#004488>"a == b"</font>);
    <font color=#0000ff>else</font> 
      System.out.println(<font color=#004488>"a != b"</font>);
    System.out.println(<font color=#004488>"a = "</font> + a);
    System.out.println(<font color=#004488>"b = "</font> + b);
    MyObject c = <font color=#0000ff>new</font> MyObject(47);
    MyObject d = f(c);
    <font color=#0000ff>if</font>(c == d) 
      System.out.println(<font color=#004488>"c == d"</font>);
    <font color=#0000ff>else</font> 
      System.out.println(<font color=#004488>"c != d"</font>);
    System.out.println(<font color=#004488>"c = "</font> + c);
    System.out.println(<font color=#004488>"d = "</font> + d);
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">First of all, <B>clone(&#160;)</B> must
be accessible so you must make it <B>public</B>. Second, for the initial part of
your <B>clone(&#160;)</B> operation you should call the base-class version of
<B>clone(&#160;)</B>. The <B>clone(&#160;)</B> that&#8217;s being called here is
the one that&#8217;s predefined inside <B>Object</B>, and you can call it
because it&#8217;s <B>protected</B> and thereby accessible in derived classes.

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

<backtalk:display ID=TIJ3_APPENDIXA_I21>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>Object.clone(&#160;)</B> figures out
how big the object is, creates enough memory for a new one, and copies all the
bits from the old to the new. This is called a
<A NAME="Index2235"></A><I>bitwise copy,</I> and is typically what you&#8217;d
expect a <B>clone(&#160;)</B> method to do. But before
<B>Object.clone(&#160;)</B> performs its operations, it first checks to see if a
class is <B>Cloneable</B>&#8212;that is, whether it implements the
<B>Cloneable</B> interface. If it doesn&#8217;t, <B>Object.clone(&#160;)</B>
throws a <A NAME="Index2236"></A><B>CloneNotSupportedException</B> to indicate
that you can&#8217;t clone it. Thus, you&#8217;ve got to surround your call to
<B>super.clone(&#160;)</B> with a try-catch block, to catch an exception that
should never happen (because you&#8217;ve implemented the <B>Cloneable</B>
interface). 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I21' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXA_I22>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In <B>LocalCopy</B>, the two methods
<B>g(&#160;)</B> and <B>f(&#160;)</B> demonstrate the difference between the two
approaches for argument passing. <B>g(&#160;)</B> shows passing by reference in
which it modifies the outside object and returns a reference to that outside
object, while <B>f(&#160;)</B> clones the argument, thereby decoupling it and
leaving the original object alone. It can then proceed to do whatever it wants,
and even to return a reference to this new object without any ill effects to the
original. Notice the somewhat curious-looking statement:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>v = (MyObject)v.clone();</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This is where the local copy is created.
To prevent confusion by such a statement, remember that this rather strange
coding idiom is perfectly feasible in Java because every object identifier is
actually a reference. So the reference <B>v</B> is used to <B>clone(&#160;)</B>
a copy of what it refers to, and this returns a reference to the base type
<B>Object</B> (because it&#8217;s defined that way in
<B>Object.clone(&#160;)</B>) that must then be cast to the proper type.

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

<backtalk:display ID=TIJ3_APPENDIXA_I23>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In <B>main(&#160;)</B>, the difference
between the effects of the two different argument-passing approaches in the two
different methods is tested. The output is:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>a == b
a = 12
b = 12
c != d
c = 47
d = 48</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It&#8217;s important to notice that the
equivalence tests in Java do not look inside the objects being compared to see
if their values are the same. The
<A NAME="Index2237"></A><A NAME="Index2238"></A><A NAME="Index2239"></A><B>==</B>
and <B>!=</B> operators are simply comparing the <I>references</I>. If the
addresses inside the <A NAME="Index2240"></A><A NAME="Index2241"></A>references
are the same, the references are pointing to the same object and are therefore
&#8220;equal.&#8221; So what the operators are really testing is whether the
references are aliased to the same object!

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

<backtalk:display ID=TIJ3_APPENDIXA_I24>
</FONT><A NAME="_Toc375545428"></A><A NAME="_Toc481064931"></A><BR></P></DIV>
<A NAME="Heading609"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
The effect of Object.clone(&#160;)</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">What actually happens when
<A NAME="Index2242"></A><A NAME="Index2243"></A><B>Object.clone(&#160;)</B> is
called that makes it so essential to call
<A NAME="Index2244"></A><A NAME="Index2245"></A><B>super.clone(&#160;)</B> when
you override <B>clone(&#160;)</B> in your class? The <B>clone(&#160;)</B> method
in the root class is responsible for creating the correct amount of storage and
making the bitwise copy of the bits from the original object into the new
object&#8217;s storage. That is, it doesn&#8217;t just make storage and copy an
<B>Object</B>&#8212;it actually figures out the size of the precise object
that&#8217;s being copied and duplicates that. Since all this is happening from
the code in the <B>clone(&#160;)</B> method defined in the root class (that has
no idea what&#8217;s being inherited from it), you can guess that the process
involves <A NAME="Index2246"></A>RTTI to determine the actual object
that&#8217;s being cloned. This way, the <B>clone(&#160;)</B> method can create
the proper amount of storage and do the correct bitcopy for that type.

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

<backtalk:display ID=TIJ3_APPENDIXA_I25>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Whatever you do, the first part of the
cloning process should normally be a call to <B>super.clone(&#160;)</B>. This
establishes the groundwork for the cloning operation by making an exact
duplicate. At this point you can perform other operations necessary to complete
the cloning. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I25' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXA_I26>

⌨️ 快捷键说明

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