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

📄 tij0128.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 3 页
字号:
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
first class, 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Ordinary</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
represents the kinds of classes we&#8217;ve seen throughout the book: no
support for cloning, but as it turns out, no prevention of cloning either. But
if you have a handle to an 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Ordinary</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object that might have been upcast from a more derived class, you can&#8217;t
tell if it can be cloned or not.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>WrongClone</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
shows an incorrect way to implement cloning. It does override 
</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">
and makes that method 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
but it doesn&#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">,
so when 
</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">
is called (which results in a call to 
</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">),
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CloneNotSupportedException</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is thrown so the cloning doesn&#8217;t work.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>IsCloneable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
you can see all the right actions performed for cloning: 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is overridden and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cloneable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is implemented. However, this 
</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 and several others that follow in this example 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>do
not
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
catch 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CloneNotSupportedException,</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
but instead pass it through to the caller, who must then put a try-catch block
around it. In your own 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods you will typically catch 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CloneNotSupportedException</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>inside</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
rather than passing it through. As you&#8217;ll see, in this example it&#8217;s
more informative to pass the exceptions through.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>NoMore</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
attempts to &#8220;turn off&#8221; cloning in the way that the Java designers
intended: in the derived class 
</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 throw 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CloneNotSupportedException</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
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
in class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TryMore</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
properly 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">,
and this resolves to 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>NoMore.clone(&#160;),</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
which throws an exception and prevents cloning.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">But
what if the programmer doesn&#8217;t follow the &#8220;proper&#8221; path of
calling <A NAME="Index1485"></A><A NAME="Index1486"></A></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">
inside 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">
method? In 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>BackOn</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you can see how this can happen. This class uses a separate method 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>duplicate(&#160;)
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">to
make a copy of the current object and calls this method inside 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>instead</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
of calling 
</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">.
The exception is never thrown and the new class is cloneable. You can&#8217;t
rely on throwing an exception to prevent making a cloneable class. The only
sure-fire solution is shown in 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ReallyNoMore</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which is 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>final</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and thus cannot be inherited. That means 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">
throws an exception in the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>final</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class, it cannot be modified with inheritance and the prevention of cloning is
assured. (You cannot explicitly call 
</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">from
a class that has an arbitrary level of inheritance; you are limited to calling 
</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">
which has access to only the direct base class.) Thus, if you make any objects
that involve security issues, you&#8217;ll want to make those classes 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>final</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
first method you see in class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CheckCloneable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>tryToClone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which takes any 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Ordinary</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object and checks to see whether it&#8217;s cloneable with 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>instanceof</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
If so, it casts the object to an 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>IsCloneable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
calls 
</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 casts the result back to 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Ordinary</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
catching any exceptions that are thrown. Notice the use of run-time type
identification (see Chapter 11) to print out the class name so you can see
what&#8217;s happening.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
different types of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Ordinary</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects are created and upcast to 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Ordinary</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in the array definition. The first two lines of code after that create a plain 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Ordinary</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object and try to clone it. However, this code will not compile because 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>protected</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method in 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The remainder of the code steps through the array and tries to clone each
object, reporting the success or failure of each. The output is:
</FONT><P></DIV>

<font color="#990000"><PRE>Attempting IsCloneable
Cloned IsCloneable
Attempting NoMore
Could not clone NoMore
Attempting TryMore
Could not clone TryMore
Attempting BackOn
Cloned BackOn
Attempting ReallyNoMore
Could not clone ReallyNoMore </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">So
to summarize, if you want a class to be cloneable:
</FONT><P></DIV>
<OL>
<LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	Implement
the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cloneable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
interface.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	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">.</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	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">
inside your 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	Capture
exceptions inside your 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT></OL><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
will produce the most convenient effects.
</FONT><a name="_Toc375545432"></a><a name="_Toc408018668"></a><P></DIV>
<A NAME="Heading381"></A><H3 ALIGN=LEFT>
The
copy-constructor
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Cloning
can seem to be a complicated process to set up. It might seem like there should
be an alternative. One approach that might occur to you (especially if
you&#8217;re a C++ programmer) is to make a special constructor whose job it is
to duplicate an object. In C++, this is called the <A NAME="Index1487"></A><A NAME="Index1488"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>copy
constructor
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
At first, this seems like the obvious solution. Here&#8217;s an example:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: CopyConstructor.java</font>
<font color="#009900">// A constructor for copying an object</font>
<font color="#009900">// of the same type, as an attempt to create</font>
<font color="#009900">// a local copy.</font>

<font color="#0000ff">class</font> FruitQualities {
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> weight;
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> color;
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> firmness;
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> ripeness;
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> smell;
  <font color="#009900">// etc.</font>
  FruitQualities() { <font color="#009900">// Default constructor</font>
    <font color="#009900">// do something meaningful...</font>
  }
  <font color="#009900">// Other constructors:</font>
  <font color="#009900">// ...</font>
  <font color="#009900">// Copy constructor:</font>
  FruitQualities(FruitQualities f) {
    weight = f.weight;
    color = f.color;
    firmness = f.firmness;
    ripeness = f.ripeness;
    smell = f.smell;
    <font color="#009900">// etc.</font>
  }
}

<font color="#0000ff">class</font> Seed {
  <font color="#009900">// Members...</font>
  Seed() { <font color="#009900">/* Default constructor */</font> }
  Seed(Seed s) { <font color="#009900">/* Copy constructor */</font> }
}

<font color="#0000ff">class</font> Fruit {
  <font color="#0000ff">private</font> FruitQualities fq;
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> seeds;
  <font color="#0000ff">private</font> Seed[] s;
  Fruit(FruitQualities q, <font color="#0000ff">int</font> seedCount) { 

⌨️ 快捷键说明

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