📄 tij0087.html
字号:
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
false
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>boolean</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">Array
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>c</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
shows the creation of the array object followed by the assignment of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Weeble</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects to all the slots in the array. Array
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>d</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
shows the “aggregate initialization” syntax that causes the array
object to be created (implicitly with
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>new</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
on the heap, just like for array
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>c</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>and</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
initialized with
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Weeble</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects, all in one statement.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
expression
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">a
= d;
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">shows
how you can take a handle that’s attached to one array object and assign
it to another array object, just as you can do with any other type of object
handle. Now both
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>a</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>d</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
are pointing to the same array object on the heap.
</FONT><P></DIV><DIV ALIGN=LEFT><A NAME="Index734"></A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Java
1.1 adds a new array initialization syntax, which could be thought of as a
“dynamic aggregate initialization.” The Java 1.0<A NAME="Index735"></A>
aggregate initialization used by
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>d</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
must be used at the point of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>d</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">’s
definition, but with the Java 1.1 syntax you can create and initialize an array
object anywhere. For example, suppose
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>hide( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is a method that takes an array of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Weeble</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects. You could call it by saying:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">hide(d);</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">but
in Java 1.1 you can also dynamically create the array you want to pass as the
argument:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">hide(new
Weeble[] { new Weeble(), new Weeble() });
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
new syntax provides a more convenient way to write code in some situations.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
second part of the above example shows that primitive arrays work just like
object arrays
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>except</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that primitive arrays hold the primitive values directly.
</FONT><a name="_Toc375545349"></a><P></DIV>
<A NAME="Heading243"></A><H4 ALIGN=LEFT>
Collections
of primitives
<P><A NAME="Index736"></A><A NAME="Index737"></A></H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Collection
classes can hold only handles to objects. An array, however, can be created to
hold primitives directly, as well as handles to objects. It
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>is</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
possible to use the “wrapper” classes such as
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Integer</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Double,</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
etc. to place primitive values inside a collection, but as you’ll see
later in this chapter in the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>WordCount.java</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
example, the wrapper classes for primitives are only somewhat useful anyway.
Whether you put primitives in arrays or wrap them in a class that’s
placed in a collection is a question of efficiency. It’s much more
efficient to create and access an array of primitives than a collection of
wrapped primitives.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Of
course, if you’re using a primitive type and you need the flexibility of
a collection that automatically expands when more space is needed, the array
won’t work and you’re forced to use a collection of wrapped
primitives. You might think that there should be a specialized type of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for each of the primitive data types, but Java doesn’t provide this for
you. Some sort of templatizing mechanism might someday provide a better way for
Java to handle this problem.
</FONT><A NAME="fnB32" HREF="#fn32">[32]</A><a name="_Toc408018565"></a><P></DIV>
<A NAME="Heading244"></A><H3 ALIGN=LEFT>
Returning
an array
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Suppose
you’re writing a method and you don’t just want to return one
thing, but a whole bunch of things. Languages like C and C++ make this
difficult because you can’t just return an array, only a pointer to an
array. This introduces problems because it becomes messy to control the
lifetime of the array, which easily leads to memory leaks.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Java
takes a similar approach, but you just “return an array.” Actually,
of course, you’re returning a handle to an array, but with Java you never
worry about responsibility for that array – it will be around as long as
you need it, and the garbage collector will clean it up when you’re done.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">As
an example, consider returning an array of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">:</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: IceCream.java</font>
<font color="#009900">// Returning arrays from methods</font>
<font color="#0000ff">public</font> <font color="#0000ff">class</font> IceCream {
<font color="#0000ff">static</font> String[] flav = {
"Chocolate", "Strawberry",
"Vanilla Fudge Swirl", "Mint Chip",
"Mocha Almond Fudge", "Rum Raisin",
"Praline Cream", "Mud Pie"
};
<font color="#0000ff">static</font> String[] flavorSet(<font color="#0000ff">int</font> n) {
<font color="#009900">// Force it to be positive & within bounds:</font>
n = Math.abs(n) % (flav.length + 1);
String[] results = <font color="#0000ff">new</font> String[n];
<font color="#0000ff">int</font>[] picks = <font color="#0000ff">new</font> <font color="#0000ff">int</font>[n];
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < picks.length; i++)
picks[i] = -1;
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < picks.length; i++) {
retry:
<font color="#0000ff">while</font>(<font color="#0000ff">true</font>) {
<font color="#0000ff">int</font> t =
(<font color="#0000ff">int</font>)(Math.random() * flav.length);
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> j = 0; j < i; j++)
<font color="#0000ff">if</font>(picks[j] == t) <font color="#0000ff">continue</font> retry;
picks[i] = t;
results[i] = flav[t];
<font color="#0000ff">break</font>;
}
}
<font color="#0000ff">return</font> results;
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < 20; i++) {
System.out.println(
"flavorSet(" + i + ") = ");
String[] fl = flavorSet(flav.length);
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> j = 0; j < fl.length; j++)
System.out.println("\t" + fl[j]);
}
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
method
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>flavorSet( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
creates an array of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>results</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The size of this array is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>n</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
determined by the argument you pass into the method. Then it proceeds to choose
flavors randomly from the array
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>flav</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and place them into
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>results</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which it finally returns. Returning an array is just like returning any other
object – it’s a handle. It’s not important that the array was
created within
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>flavorSet( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
or that the array was created anyplace else, for that matter. The garbage
collector takes care of cleaning up the array when you’re done with it,
and the array will persist for as long as you need it.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">As
an aside, notice that when
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>flavorSet( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
chooses flavors randomly, it ensures that a random choice hasn’t been
picked before. This is performed in a seemingly infinite
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>while</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
loop that keeps making random choices until it finds one that’s not
already in the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>picks</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
array. (Of course, a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
comparison could also have been performed to see if the random choice was
already in the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>results</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
array, but
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
comparisons are inefficient.) If it’s successful it adds the entry and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>break</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s
out to go find the next one (
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>i
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">gets
incremented). But if
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>t</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is a number that’s already in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>picks</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
then a labeled
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>continue</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is used to jump back two levels, which forces a new
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>t</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to be selected. It’s particularly convincing to watch this happen with a
debugger.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
prints out 20 full sets of flavors, so you can see that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>flavorSet( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
chooses the flavors in a random order each time. It’s easiest to see this
if you redirect the output into a file. And while you’re looking at the
file, remember, you’re not really hungry. (You just
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>want</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
the ice cream, you don’t
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>need</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
it.)
</FONT><a name="_Toc375545350"></a><a name="_Toc408018566"></a><P></DIV>
<HR><DIV ALIGN=LEFT><A NAME="fn32" HREF="#fnB32">[32]</A><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
This is one of the places where C++ is distinctly superior to Java, since C++
supports
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><I>parameterized
types
</I></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
with the
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><B>template</B></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
keyword.
</FONT><P></DIV>
<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0086.html">Prev</a> | <a href="tij0088.html">Next</a>
</div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -