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

📄 tij0128.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 3 页
字号:
<html><body>

<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0127.html">Prev</a> | <a href="tij0129.html">Next</a>
</td>
</tr></table>
<hr>

<H2 ALIGN=LEFT>
Controlling
cloneability
</H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
might suggest that, to remove <A NAME="Index1483"></A><A NAME="Index1484"></A>clonability,
the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method simply be made 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
but this won&#8217;t work since you cannot take a base-class method and make it
more 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in a derived class. So it&#8217;s not that simple. And yet, it&#8217;s
necessary to be able to control whether an object can be cloned. There are
actually a number of attitudes you can take to this in a class that you design:
</FONT><P></DIV>
<OL>
<LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	Indifference.
You don&#8217;t do anything about cloning, which means that your class
can&#8217;t be cloned but a class that inherits from you can add cloning if it
wants. This works only if the default 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object.clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
will do something reasonable with all the fields in your class.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	Support
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Follow the standard practice of implementing 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cloneable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and overriding 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
In the overridden 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you call 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>super.clone(&#160;)
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">and
catch all exceptions (so your overridden 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
doesn&#8217;t throw any exceptions).
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	Support
cloning conditionally. If your class holds handles to other objects that might
or might not be cloneable (an example of this is a collection class), you can
try to clone all of the objects that you have handles to as part of your
cloning, and if they throw exceptions just pass them through. For example,
consider a special sort of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that tries to clone all the objects it holds. When you write such a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you don&#8217;t know what sort of objects the client programmer might put into
your 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
so you don&#8217;t know whether they can be cloned.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	Don&#8217;t
implement 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cloneable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
but override 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>protected</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
producing the correct copying behavior for any fields. This way, anyone
inheriting from this class can override 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and call 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>super.clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to produce the correct copying behavior. Note that your implementation can and
should invoke 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>super.clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
even though that method expects a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cloneable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object (it will throw an exception otherwise), because no one will directly
invoke it on an object of your type. It will get invoked only through a derived
class, which, if it is to work successfully, implements 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cloneable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	Try
to prevent cloning by not implementing 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cloneable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and overriding 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to throw an exception. This is successful only if any class derived from this
calls 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>super.clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in its redefinition of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Otherwise, a programmer may be able to get around it.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	Prevent
cloning by making your class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>final</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
If 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
has not been overridden by any of your ancestor classes, then it can&#8217;t
be. If it has, then override it again and throw 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CloneNotSupportedException</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Making the class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>final
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">is
the only way to guarantee that cloning is prevented. In addition, when dealing
with security objects or other situations in which you want to control the
number of objects created you should make all constructors 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and provide one or more special methods for creating objects. That way, these
methods can restrict the number of objects created and the conditions in which
they&#8217;re created. (A particular case of this is the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>singleton</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
pattern shown in Chapter 16.)
</FONT></OL><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Here&#8217;s
an example that shows the various ways cloning can be implemented and then,
later in the hierarchy, &#8220;turned off:&#8221;
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: CheckCloneable.java</font>
<font color="#009900">// Checking to see if a handle can be cloned</font>

<font color="#009900">// Can't clone this because it doesn't</font>
<font color="#009900">// override clone():</font>
<font color="#0000ff">class</font> Ordinary {}

<font color="#009900">// Overrides clone, but doesn't implement</font>
<font color="#009900">// Cloneable:</font>
<font color="#0000ff">class</font> WrongClone <font color="#0000ff">extends</font> Ordinary {
  <font color="#0000ff">public</font> Object clone()
      <font color="#0000ff">throws</font> CloneNotSupportedException {
    <font color="#0000ff">return</font> <font color="#0000ff">super</font>.clone(); <font color="#009900">// Throws exception</font>
  }
}

<font color="#009900">// Does all the right things for cloning:</font>
<font color="#0000ff">class</font> IsCloneable <font color="#0000ff">extends</font> Ordinary 
    <font color="#0000ff">implements</font> Cloneable {
  <font color="#0000ff">public</font> Object clone() 
      <font color="#0000ff">throws</font> CloneNotSupportedException {
    <font color="#0000ff">return</font> <font color="#0000ff">super</font>.clone();
  }
}

<font color="#009900">// Turn off cloning by throwing the exception:</font>
<font color="#0000ff">class</font> NoMore <font color="#0000ff">extends</font> IsCloneable {
  <font color="#0000ff">public</font> Object clone() 
      <font color="#0000ff">throws</font> CloneNotSupportedException {
    <font color="#0000ff">throw</font> <font color="#0000ff">new</font> CloneNotSupportedException();
  }
}

<font color="#0000ff">class</font> TryMore <font color="#0000ff">extends</font> NoMore {
  <font color="#0000ff">public</font> Object clone() 
      <font color="#0000ff">throws</font> CloneNotSupportedException {
    <font color="#009900">// Calls NoMore.clone(), throws exception:</font>
    <font color="#0000ff">return</font> <font color="#0000ff">super</font>.clone();
  }
}

<font color="#0000ff">class</font> BackOn <font color="#0000ff">extends</font> NoMore {
  <font color="#0000ff">private</font> BackOn duplicate(BackOn b) {
    <font color="#009900">// Somehow make a copy of b</font>
    <font color="#009900">// and return that copy. This is a dummy</font>
    <font color="#009900">// copy, just to make the point:</font>
    <font color="#0000ff">return</font> <font color="#0000ff">new</font> BackOn();
  }
  <font color="#0000ff">public</font> Object clone() {
    <font color="#009900">// Doesn't call NoMore.clone():</font>
    <font color="#0000ff">return</font> duplicate(<font color="#0000ff">this</font>);
  }
}

<font color="#009900">// Can't inherit from this, so can't override</font>
<font color="#009900">// the clone method like in BackOn:</font>
<font color="#0000ff">final</font> <font color="#0000ff">class</font> ReallyNoMore <font color="#0000ff">extends</font> NoMore {}

<font color="#0000ff">public</font> <font color="#0000ff">class</font> CheckCloneable {
  <font color="#0000ff">static</font> Ordinary tryToClone(Ordinary ord) {
    String id = ord.getClass().getName();
    Ordinary x = <font color="#0000ff">null</font>;
    <font color="#0000ff">if</font>(ord <font color="#0000ff">instanceof</font> Cloneable) {
      <font color="#0000ff">try</font> {
        System.out.println("Attempting " + id);
        x = (Ordinary)((IsCloneable)ord).clone();
        System.out.println("Cloned " + id);
      } <font color="#0000ff">catch</font>(CloneNotSupportedException e) {
        System.out.println(
          "Could not clone " + id);
      }
    }
    <font color="#0000ff">return</font> x;
  }
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
    <font color="#009900">// Upcasting:</font>
    Ordinary[] ord = { 
      <font color="#0000ff">new</font> IsCloneable(),
      <font color="#0000ff">new</font> WrongClone(),
      <font color="#0000ff">new</font> NoMore(),
      <font color="#0000ff">new</font> TryMore(),
      <font color="#0000ff">new</font> BackOn(),
      <font color="#0000ff">new</font> ReallyNoMore(),
    };
    Ordinary x = <font color="#0000ff">new</font> Ordinary();
    <font color="#009900">// This won't compile, since clone() is</font>
    <font color="#009900">// protected in Object:</font>
    <font color="#009900">//! x = (Ordinary)x.clone();</font>
    <font color="#009900">// tryToClone() checks first to see if</font>
    <font color="#009900">// a class implements Cloneable:</font>
    <font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i &lt; ord.length; i++)
      tryToClone(ord[i]);
  }

⌨️ 快捷键说明

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