📄 appenda.htm
字号:
}
<font color=#0000ff>public</font> <font color=#0000ff>class</font> AddingClone {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Int2 x = <font color=#0000ff>new</font> Int2(10);
Int2 x2 = (Int2)x.clone();
x2.increment();
System.out.println(
<font color=#004488>"x = "</font> + x + <font color=#004488>", x2 = "</font> + x2);
<font color=#009900>// Anything inherited is also cloneable:</font>
Int3 x3 = <font color=#0000ff>new</font> Int3(7);
x3 = (Int3)x3.clone();
ArrayList v = <font color=#0000ff>new</font> ArrayList();
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < 10; i++ )
v.add(<font color=#0000ff>new</font> Int2(i));
System.out.println(<font color=#004488>"v: "</font> + v);
ArrayList v2 = (ArrayList)v.clone();
<font color=#009900>// Now clone each element:</font>
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < v.size(); i++)
v2.set(i, ((Int2)v2.get(i)).clone());
<font color=#009900>// Increment all v2's elements:</font>
<font color=#0000ff>for</font>(Iterator e = v2.iterator();
e.hasNext(); )
((Int2)e.next()).increment();
<font color=#009900>// See if it changed v's elements:</font>
System.out.println(<font color=#004488>"v: "</font> + v);
System.out.println(<font color=#004488>"v2: "</font> + v2);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>Int3</B> is inherited from <B>Int2</B>
and a new primitive member <B>int j </B>is added. You might think that
you’d need to override <B>clone( )</B> again to make sure <B>j</B> is
copied, but that’s not the case. When <B>Int2</B>’s
<B>clone( )</B> is called as <B>Int3</B>’s <B>clone( )</B>, it
calls <B>Object.clone( ),</B> which determines that it’s working with
an <B>Int3</B> and duplicates all the bits in the <B>Int3</B>. As long as you
don’t add references that need to be cloned, the one call to
<B>Object.clone( )</B> performs all of the necessary duplication,
regardless of how far down in the hierarchy <B>clone( )</B> is defined.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I32'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I33>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can see what’s necessary in
order to do a deep copy of an <B>ArrayList</B>: after the <B>ArrayList</B> is
cloned, you have to step through and clone each one of the objects pointed to by
the <B>ArrayList</B>. You’d have to do something similar to this to do a
deep copy of a <B>HashMap</B>.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I33'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I34>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The remainder of the example shows that
the cloning did happen by showing that, once an object is cloned, you can change
it and the original object is left untouched.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I34'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I35>
</FONT><A NAME="_Toc375545429"></A><A NAME="_Toc481064934"></A><BR></P></DIV>
<A NAME="Heading612"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Deep copy via serialization</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When you consider Java’s object
serialization (introduced in Chapter 11), you might observe that an object
that’s serialized and then deserialized is, in effect, cloned.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I35'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I36>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">So why not use
<A NAME="Index2253"></A><A NAME="Index2254"></A>serialization to perform deep
copying? Here’s an example that compares the two approaches by timing
them:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixa:Compete.java</font>
<font color=#0000ff>import</font> java.io.*;
<font color=#0000ff>class</font> Thing1 <font color=#0000ff>implements</font> Serializable {}
<font color=#0000ff>class</font> Thing2 <font color=#0000ff>implements</font> Serializable {
Thing1 o1 = <font color=#0000ff>new</font> Thing1();
}
<font color=#0000ff>class</font> Thing3 <font color=#0000ff>implements</font> Cloneable {
<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>"Thing3 can't clone"</font>);
}
<font color=#0000ff>return</font> o;
}
}
<font color=#0000ff>class</font> Thing4 <font color=#0000ff>implements</font> Cloneable {
Thing3 o3 = <font color=#0000ff>new</font> Thing3();
<font color=#0000ff>public</font> Object clone() {
Thing4 o = <font color=#0000ff>null</font>;
<font color=#0000ff>try</font> {
o = (Thing4)<font color=#0000ff>super</font>.clone();
} <font color=#0000ff>catch</font>(CloneNotSupportedException e) {
System.err.println(<font color=#004488>"Thing4 can't clone"</font>);
}
<font color=#009900>// Clone the field, too:</font>
o.o3 = (Thing3)o3.clone();
<font color=#0000ff>return</font> o;
}
}
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Compete {
<font color=#0000ff>static</font> <font color=#0000ff>final</font> <font color=#0000ff>int</font> SIZE = 5000;
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args)
<font color=#0000ff>throws</font> Exception {
Thing2[] a = <font color=#0000ff>new</font> Thing2[SIZE];
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < a.length; i++)
a[i] = <font color=#0000ff>new</font> Thing2();
Thing4[] b = <font color=#0000ff>new</font> Thing4[SIZE];
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < b.length; i++)
b[i] = <font color=#0000ff>new</font> Thing4();
<font color=#0000ff>long</font> t1 = System.currentTimeMillis();
ByteArrayOutputStream buf =
<font color=#0000ff>new</font> ByteArrayOutputStream();
ObjectOutputStream o =
<font color=#0000ff>new</font> ObjectOutputStream(buf);
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < a.length; i++)
o.writeObject(a[i]);
<font color=#009900>// Now get copies:</font>
ObjectInputStream in =
<font color=#0000ff>new</font> ObjectInputStream(
<font color=#0000ff>new</font> ByteArrayInputStream(
buf.toByteArray()));
Thing2[] c = <font color=#0000ff>new</font> Thing2[SIZE];
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < c.length; i++)
c[i] = (Thing2)in.readObject();
<font color=#0000ff>long</font> t2 = System.currentTimeMillis();
System.out.println(
<font color=#004488>"Duplication via serialization: "</font> +
(t2 - t1) + <font color=#004488>" Milliseconds"</font>);
<font color=#009900>// Now try cloning:</font>
t1 = System.currentTimeMillis();
Thing4[] d = <font color=#0000ff>new</font> Thing4[SIZE];
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < d.length; i++)
d[i] = (Thing4)b[i].clone();
t2 = System.currentTimeMillis();
System.out.println(
<font color=#004488>"Duplication via cloning: "</font> +
(t2 - t1) + <font color=#004488>" Milliseconds"</font>);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>Thing2</B> and <B>Thing4</B> contain
member objects so that there’s some deep copying going on. It’s
interesting to notice that while <B>Serializable</B> classes are easy to set up,
there’s much more work going on to duplicate them. Cloning involves a lot
of work to set up the class, but the actual duplication of objects is relatively
simple. The results really tell the tale. Here is the output from three
different runs:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Duplication via serialization: 940 Milliseconds
Duplication via cloning: 50 Milliseconds
Duplication via serialization: 710 Milliseconds
Duplication via cloning: 60 Milliseconds
Duplication via serialization: 770 Milliseconds
Duplication via cloning: 50 Milliseconds</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Despite the significant time difference
between serialization and cloning, you’ll also notice that the
serialization technique seems to vary more in its duration, while cloning tends
to be more stable.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I36'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I37>
</FONT><A NAME="_Toc481064935"></A><BR></P></DIV>
<A NAME="Heading613"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Adding cloneability <BR>further down a hierarchy</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you create a new class, its base class
defaults to <B>Object</B>, which defaults to noncloneability (as you’ll
see in the next section). As long as you don’t explicitly add
cloneability, you won’t get it.
<A NAME="Index2255"></A><A NAME="Index2256"></A>But you can add it in at any
layer and it will then be cloneable from that layer downward, like
this:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixa:HorrorFlick.java</font>
<font color=#009900>// You can insert Cloneability </font>
<font color=#009900>// at any level of inheritance.</font>
<font color=#0000ff>import</font> java.util.*;
<font color=#0000ff>class</font> Person {}
<font color=#0000ff>class</font> Hero <font color=#0000ff>extends</font> Person {}
<font color=#0000ff>class</font> Scientist <font color=#0000ff>extends</font> Person
<font color=#0000ff>implements</font> Cloneable {
<font color=#0000ff>public</font> Object clone() {
<font color=#0000ff>try</font> {
<font color=#0000ff>return</font> <font color=#0000ff>super</font>.clone();
} <font color=#0000ff>catch</font>(CloneNotSupportedException e) {
<font color=#009900>// this should never happen:</font>
<font color=#009900>// It's Cloneable already!</font>
<font color=#0000ff>throw</font> <font color=#0000ff>new</font> InternalError();
}
}
}
<font color=#0000ff>class</font> MadScientist <font color=#0000ff>extends</font> Scientist {}
<font color=#0000ff>public</font> <font color=#0000ff>class</font> HorrorFlick {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Person p = <font color=#0000ff>new</font> Person();
Hero h = <font color=#0000ff>new</font> Hero();
Scientist s = <font color=#0000ff>new</font> Scientist();
MadScientist m = <font color=#0000ff>new</font> MadScientist();
<font color=#009900>// p = (Person)p.clone(); // Compile error</font>
<font color=#009900>// h = (Hero)h.clone(); // Compile error</font>
s = (Scientist)s.clone();
m = (MadScientist)m.clone();
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Before cloneability was added, the
compiler stopped you from trying to clone things. When cloneability is added in
<B>Scientist</B>, then <B>Scientist</B> and all its descendants are cloneable.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I37'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I38>
</FONT><A NAME="_Toc375545430"></A><A NAME="_Toc481064936"></A><BR></P></DIV>
<A NAME="Heading614"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Why this strange design?</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If all this seems to be a strange scheme,
that&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -