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

📄 tij0129.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 5 页
字号:
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> Immutable2 modify1(Immutable2 y){
    Immutable2 val = y.add(12);
    val = val.multiply(3);
    val = val.add(11);
    val = val.multiply(2);
    <font color="#0000ff">return</font> val;
  }
  <font color="#009900">// This produces the same result:</font>
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> Immutable2 modify2(Immutable2 y){
    Mutable m = y.makeMutable();
    m.add(12).multiply(3).add(11).multiply(2);
    <font color="#0000ff">return</font> m.makeImmutable2();
  }
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
    Immutable2 i2 = <font color="#0000ff">new</font> Immutable2(47);
    Immutable2 r1 = modify1(i2);
    Immutable2 r2 = modify2(i2);
    System.out.println("i2 = " + i2.read());
    System.out.println("r1 = " + r1.read());
    System.out.println("r2 = " + r2.read());
  }
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Immutable2
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">contains
methods that, as before, preserve the immutability of the objects by producing
new objects whenever a modification is desired. These are the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>add(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>multiply(&#160;)
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">methods.
The companion class is called 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Mutable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and it also has 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>add(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>multiply(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods, but these modify the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Mutable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object rather than making a new one. In addition, 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Mutable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
has a method to use its data to produce an 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Immutable2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object and vice versa. 
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
two static methods 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>modify1(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>modify2(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
show two different approaches to producing the same result. In 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>modify1(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
everything is done within the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Immutable2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class and you can see that four new 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Immutable2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects are created in the process. (And each time 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>val</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is reassigned, the previous object becomes garbage.)
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
the method 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>modify2(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you can see that the first action is to take the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Immutable2
y
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and produce a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Mutable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
from it. (This is just like calling 
</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 you saw earlier, but this time a different type of object is created.) Then
the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Mutable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object is used to perform a lot of change operations 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>without</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
requiring the creation of many new objects. Finally, it&#8217;s turned back
into an 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Immutable2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Here, two new objects are created (the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Mutable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and the result 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Immutable2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
instead of four.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
approach makes sense, then, when:
</FONT><P></DIV>
<OL>
<LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	You
need immutable objects and
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	You
often need to make a lot of modifications or
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	It&#8217;s
expensive to create new immutable objects
</FONT><a name="_Toc408018672"></a></OL><A NAME="Heading386"></A><H3 ALIGN=LEFT>
Immutable
Strings
<P><A NAME="Index1494"></A><A NAME="Index1495"></A></H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Consider
the following code:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: Stringer.java</font>

<font color="#0000ff">public</font> <font color="#0000ff">class</font> Stringer {
  <font color="#0000ff">static</font> String upcase(String s) {
    <font color="#0000ff">return</font> s.toUpperCase();
  }
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
    String q = <font color="#0000ff">new</font> String("howdy");
    System.out.println(q); <font color="#009900">// howdy</font>
    String qq = upcase(q);
    System.out.println(qq); <font color="#009900">// HOWDY</font>
    System.out.println(q); <font color="#009900">// howdy</font>
  }
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>q</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is passed in to 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>upcase(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
it&#8217;s actually a copy of the handle to 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>q</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The object this handle is connected to stays put in a single physical location.
The handles are copied as they are passed around.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Looking
at the definition for 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>upcase(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you can see that the handle that&#8217;s passed in has the name 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>s</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and it exists for only as long as the body of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>upcase(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is being executed. When 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>upcase(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
completes, the local handle 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>s</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
vanishes. 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>upcase(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
returns the result, which is the original string with all the characters set to
uppercase. Of course, it actually returns a handle to the result. But it turns
out that the handle that it returns is for a new object, and the original 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>q</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is left alone. How does this happen?
</FONT><P></DIV>
<A NAME="Heading387"></A><H4 ALIGN=LEFT>
Implicit
constants
<P><A NAME="Index1496"></A></H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you say:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">String
s = "asdf";
</FONT></TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">String
x = Stringer.upcase(s);
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">do
you really want the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>upcase(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method to 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>change</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
the argument? In general, you don&#8217;t, because an argument usually looks to
the reader of the code as a piece of information provided to the method, not
something to be modified. This is an important guarantee, since it makes code
easier to write and understand.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
C++, the availability of this guarantee was important enough to put in a
special keyword, <A NAME="Index1497"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>const</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
to allow the programmer to ensure that a handle (pointer or reference in C++)
could not be used to modify the original object. But then the C++ programmer
was required to be diligent and remember to use 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>const</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
everywhere. It can be confusing and easy to forget.
</FONT><a name="_Toc375545435"></a><P></DIV>
<A NAME="Heading388"></A><H4 ALIGN=LEFT>
Overloading
&#8216;+&#8217; and the StringBuffer
</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Objects
of the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class are designed to be immutable, using the technique shown previously. If
you examine the online documentation
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">for
the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class (which is summarized a little later in this chapter), you&#8217;ll see
that every method in the class that appears to modify a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
really creates and returns a brand new 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object containing the modification. The original 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is left untouched. Thus, there&#8217;s no feature in Java like C++&#8217;s 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>const</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to make the compiler support the immutability of your objects. If you want it,
you have to wire it in yourself, like 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
does.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Since
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">objects
are immutable, you can <A NAME="Index1498"></A>alias
to a particular 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">as
many times as you want. Because it&#8217;s read-only there&#8217;s no
possibility that one handle will change something that will affect the other
handles. So a read-only object solves the aliasing problem nicely.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">It
also seems possible to handle all the cases in which you need a modified object
by creating a brand new version of the object with the modifications, as 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
does. However, for some operations this isn&#8217;t efficient. A case in point
is the <A NAME="Index1499"></A><A NAME="Index1500"></A>operator
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>&#8216;+</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">&#8217;
that has been overloaded for 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects. <A NAME="Index1501"></A><A NAME="Index1502"></A>Overloading
means that it has been given an extra meaning when used with a particular
class. (The &#8216;
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>+</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">&#8217;
and &#8216;
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>+=</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">&#8216;
for 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
are the only operators that are overloaded in Java and Java does not allow the
programmer to overload any others
</FONT><A NAME="fnB52" HREF="#fn52">[52]</A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">).</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
used with 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects, the &#8216;
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>+</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">&#8217;
allows you to concatenate 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s
together:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">String

⌨️ 快捷键说明

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