📄 appenda.htm
字号:
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I16'
target="_blank">Add Comment</a> ]
<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( )
</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’ll
probably want to override <B>clone( ) </B>in any further derived classes,
otherwise your (now <B>public</B>) <B>clone( )</B> will be used, and that
might not do the right thing (although, since <B>Object.clone( )</B> makes
a copy of the actual object, it might). The <B>protected</B> trick works only
once—the first time you inherit from a class that has no cloneability and
you want to make a class that’s cloneable. In any classes inherited from
your class the <B>clone( ) </B>method is available since it’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 “turn off” cloning.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I17'
target="_blank">Add Comment</a> ]
<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’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’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 “hack” because it’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>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I18'
target="_blank">Add Comment</a> ]
<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’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’t want all
types of objects to be cloneable. So <B>Object.clone( )</B> verifies that a
class implements the <B>Cloneable</B> interface. If not, it throws a
<B>CloneNotSupportedException</B> exception. So in general, you’re forced
to <B>implement Cloneable</B> as part of support for cloning.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I19'
target="_blank">Add Comment</a> ]
<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( )</B> method, you’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( )</B> must
be accessible so you must make it <B>public</B>. Second, for the initial part of
your <B>clone( )</B> operation you should call the base-class version of
<B>clone( )</B>. The <B>clone( )</B> that’s being called here is
the one that’s predefined inside <B>Object</B>, and you can call it
because it’s <B>protected</B> and thereby accessible in derived classes.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I20'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I21>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>Object.clone( )</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’d
expect a <B>clone( )</B> method to do. But before
<B>Object.clone( )</B> performs its operations, it first checks to see if a
class is <B>Cloneable</B>—that is, whether it implements the
<B>Cloneable</B> interface. If it doesn’t, <B>Object.clone( )</B>
throws a <A NAME="Index2236"></A><B>CloneNotSupportedException</B> to indicate
that you can’t clone it. Thus, you’ve got to surround your call to
<B>super.clone( )</B> with a try-catch block, to catch an exception that
should never happen (because you’ve implemented the <B>Cloneable</B>
interface).
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I21'
target="_blank">Add Comment</a> ]
<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( )</B> and <B>f( )</B> demonstrate the difference between the two
approaches for argument passing. <B>g( )</B> shows passing by reference in
which it modifies the outside object and returns a reference to that outside
object, while <B>f( )</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( )</B>
a copy of what it refers to, and this returns a reference to the base type
<B>Object</B> (because it’s defined that way in
<B>Object.clone( )</B>) that must then be cast to the proper type.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I22'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I23>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In <B>main( )</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’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
“equal.” So what the operators are really testing is whether the
references are aliased to the same object!
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I23'
target="_blank">Add Comment</a> ]
<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( )</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">What actually happens when
<A NAME="Index2242"></A><A NAME="Index2243"></A><B>Object.clone( )</B> is
called that makes it so essential to call
<A NAME="Index2244"></A><A NAME="Index2245"></A><B>super.clone( )</B> when
you override <B>clone( )</B> in your class? The <B>clone( )</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’s storage. That is, it doesn’t just make storage and copy an
<B>Object</B>—it actually figures out the size of the precise object
that’s being copied and duplicates that. Since all this is happening from
the code in the <B>clone( )</B> method defined in the root class (that has
no idea what’s being inherited from it), you can guess that the process
involves <A NAME="Index2246"></A>RTTI to determine the actual object
that’s being cloned. This way, the <B>clone( )</B> method can create
the proper amount of storage and do the correct bitcopy for that type.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I24'
target="_blank">Add Comment</a> ]
<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( )</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>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I25'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I26>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -