📄 chapter08.html
字号:
1.2<A NAME="Index777"></A> provides a radically redesigned and filled-out
library of collections.)
</FONT><A NAME="_Ref348399519"></A><A NAME="_Toc375545354"></A><A NAME="_Toc408018570"></A><BR></P></DIV>
<A NAME="Heading251"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Vector<BR><A NAME="Index778"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>Vector</B> is quite simple
to use, as you’ve seen so far. Although most of the time you’ll just
use <B>addElement( )</B> to insert objects, <B>elementAt( )</B> to get
them out one at a time, and <B>elements( )</B> to get an <B>Enumeration</B>
to the sequence, there’s also a set of other methods that can be useful.
As usual with the Java libraries, we won’t use or talk about them all
here, but be sure to look them up in the electronic documentation to get a feel
for what they can do.</FONT><BR></P></DIV>
<A NAME="Heading252"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
Crashing Java<BR><A NAME="Index779"></A></H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The Java standard collections
contain a <B>toString( )</B> method so they can produce a <B>String</B>
representation of themselves, including the objects they hold. Inside of
<B>Vector</B>, for example, the <B>toString( )</B> steps through the
elements of the <B>Vector</B> and calls <B>toString( )</B> for each one.
Suppose you’d like to print out the address of your class. It seems to
make sense to simply refer to <B>this </B>(in particular, C++ programmers are
prone to this approach):</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: CrashJava.java</font>
<font color=#009900>// One way to crash Java</font>
<font color=#0000ff>import</font> java.util.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> CrashJava {
<font color=#0000ff>public</font> String toString() {
<font color=#0000ff>return</font> <font color=#004488>"CrashJava address: "</font> + <font color=#0000ff>this</font> + <font color=#004488>"\n"</font>;
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Vector v = <font color=#0000ff>new</font> Vector();
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < 10; i++)
v.addElement(<font color=#0000ff>new</font> CrashJava());
System.out.println(v);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It turns out that if you simply
create a <B>CrashJava</B> object and print it out, you’ll get an endless
sequence of exceptions. However, if you place the <B>CrashJava</B> objects in a
<B>Vector</B> and print out that <B>Vector</B> as shown here, it can’t
handle it and you don’t even get an exception; Java just crashes. (But at
least it didn’t bring down my operating system.) This was tested with Java
1.1<A NAME="Index780"></A>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">What’s happening is automatic
type conversion for <B>String</B>s. When you say: </FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#004488>"CrashJava address: "</font> + <font color=#0000ff>this</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The compiler sees a <B>String</B>
followed by a ‘<B>+</B>’ and<B> </B>something that’s not a
<B>String</B>, so it tries to convert <B>this</B> to a <B>String</B>. It does
this conversion by calling <B>toString( )</B>, which produces a
<A NAME="Index781"></A><A NAME="Index782"></A>recursive call. When this occurs
inside a <B>Vector,</B> it appears that the
<A NAME="Index783"></A><A NAME="Index784"></A>stack overflows without the
exception-handling mechanism getting a chance to respond.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you really do want to print the
address of the object in this case, the solution is to call the <B>Object</B>
<B>toString( )</B> method, which does just that. So instead of saying
<B>this</B>, you’d say <B>super.toString( )</B>. (This only works if
you're directly inheriting from <B>Object</B> or if none of your parent classes
have overridden the <B>toString( )</B>
method).</FONT><A NAME="_Toc375545355"></A><A NAME="_Toc408018571"></A><BR></P></DIV>
<A NAME="Heading253"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
BitSet</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A
<A NAME="Index785"></A><B>BitSet</B> is really a <B>Vector</B> of bits, and it
is used if you want to efficiently store a lot of on-off information. It’s
efficient only from the standpoint of size; if you’re looking for
efficient access, it is slightly slower than using an array of some native
type.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In addition, the minimum size of
the <B>BitSet</B> is that of a long: 64 bits. This implies that if you’re
storing anything smaller, like 8 bits, a <B>BitSet</B> will be wasteful, so
you’re better off creating your own class to hold your
flags.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In a normal <B>Vector</B>, the
collection will expand as you add more elements. The <B>BitSet</B> does this as
well – sort of. That is, sometimes it works and sometimes it
doesn’t, which makes it appear that the Java version 1.0 implementation of
<B>BitSet</B> is just badly done. (It is fixed in Java
1.1.<A NAME="Index786"></A>) The following example shows how the <B>BitSet
</B>works and demonstrates the version 1.0 bug:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: Bits.java</font>
<font color=#009900>// Demonstration of BitSet</font>
<font color=#0000ff>import</font> java.util.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Bits {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Random rand = <font color=#0000ff>new</font> Random();
<font color=#009900>// Take the LSB of nextInt():</font>
<font color=#0000ff>byte</font> bt = (<font color=#0000ff>byte</font>)rand.nextInt();
BitSet bb = <font color=#0000ff>new</font> BitSet();
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 7; i >=0; i--)
<font color=#0000ff>if</font>(((1 << i) & bt) != 0)
bb.set(i);
<font color=#0000ff>else</font>
bb.clear(i);
System.out.println(<font color=#004488>"byte value: "</font> + bt);
printBitSet(bb);
<font color=#0000ff>short</font> st = (<font color=#0000ff>short</font>)rand.nextInt();
BitSet bs = <font color=#0000ff>new</font> BitSet();
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 15; i >=0; i--)
<font color=#0000ff>if</font>(((1 << i) & st) != 0)
bs.set(i);
<font color=#0000ff>else</font>
bs.clear(i);
System.out.println(<font color=#004488>"short value: "</font> + st);
printBitSet(bs);
<font color=#0000ff>int</font> it = rand.nextInt();
BitSet bi = <font color=#0000ff>new</font> BitSet();
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 31; i >=0; i--)
<font color=#0000ff>if</font>(((1 << i) & it) != 0)
bi.set(i);
<font color=#0000ff>else</font>
bi.clear(i);
System.out.println(<font color=#004488>"int value: "</font> + it);
printBitSet(bi);
<font color=#009900>// Test bitsets >= 64 bits:</font>
BitSet b127 = <font color=#0000ff>new</font> BitSet();
b127.set(127);
System.out.println(<font color=#004488>"set bit 127: "</font> + b127);
BitSet b255 = <font color=#0000ff>new</font> BitSet(65);
b255.set(255);
System.out.println(<font color=#004488>"set bit 255: "</font> + b255);
BitSet b1023 = <font color=#0000ff>new</font> BitSet(512);
<font color=#009900>// Without the following, an exception is thrown</font>
<font color=#009900>// in the Java 1.0 implementation of BitSet:</font>
<font color=#009900>// b1023.set(1023);</font>
b1023.set(1024);
System.out.println(<font color=#004488>"set bit 1023: "</font> + b1023);
}
<font color=#0000ff>static</font> <font color=#0000ff>void</font> printBitSet(BitSet b) {
System.out.println(<font color=#004488>"bits: "</font> + b);
String bbits = <font color=#0000ff>new</font> String();
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> j = 0; j < b.size() ; j++)
bbits += (b.get(j) ? <font color=#004488>"1"</font> : <font color=#004488>"0"</font>);
System.out.println(<font color=#004488>"bit pattern: "</font> + bbits);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The random number generator is used
to create a random <B>byte</B>, <B>short</B>, and <B>int</B>, and each one is
transformed into a corresponding bit pattern in a <B>BitSet</B>. This works fine
because a <B>BitSet</B> is 64 bits, so none of these cause it to increase in
size. But in Java 1.0<A NAME="Index787"></A>, when the <B>BitSet</B> is greater
than 64 bits, some strange behavior occurs. If you set a bit that’s just
one greater than the <B>BitSet</B>’s currently-allocated storage, it will
expand nicely. But if you try to set bits at higher locations than that without
first just touching the boundary, you’ll get an exception, since the
<B>BitSet</B> won’t expand properly in Java 1.0. The example shows a
<B>BitSet</B> of 512 bits being created. The constructor allocates storage for
twice that number of bits. Then if you try to set bit 1024 or greater without
first setting bit 1023, you’ll throw an exception in
<A NAME="Index788"></A>Java 1.0. Fortunately, this is fixed in Java
1.1,<A NAME="Index789"></A> but avoid using the <B>BitSet</B> if you write code
for Java
1.0.</FONT><A NAME="_Toc375545356"></A><A NAME="_Toc408018572"></A><BR></P></DIV>
<A NAME="Heading254"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Stack</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A
<A NAME="Index790"></A><B>Stack</B> is sometimes referred to as a
“last-in, first-out” (LIFO) collection. That is, whatever you
“push” on the <B>Stack</B> last is the first item you can
“pop” out. Like all of the other collections in Java, what you push
and pop are <B>Object</B>s, so you must cast what you pop.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">What’s rather odd is that
instead of using a <A NAME="Index791"></A><B>Vector</B> as a building block to
create a <B>Stack</B>, <B>Stack </B>is inherited from <B>Vector</B>. So it has
all of the characteristics and behaviors of a <B>Vector</B> <I>plus</I> some
extra <B>Stack</B> behaviors. It’s difficult to know whether the designers
explicitly decided that this was an especially useful way to do things, or
whether it was just a naïve design.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here’s a simple demonstration
of <B>Stack</B> that reads each line from an array and pushes it as a
<B>String</B>:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: Stacks.java</font>
<font color=#009900>// Demonstration of Stack Class</font>
<font color=#0000ff>import</font> java.util.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Stacks {
<font color=#0000ff>static</font> String[] months = {
<font color=#004488>"January"</font>, <font color=#004488>"February"</font>, <font color=#004488>"March"</font>, <font color=#004488>"April"</font>,
<font color=#004488>"May"</font>, <font color=#004488>"June"</font>, <font color=#004488>"July"</font>, <font color=#004488>"August"</font>, <font color=#004488>"September"</font>,
<font color=#004488>"October"</font>, <font color=#004488>"November"</font>, <font color=#004488>"December"</font> };
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Stack stk = <font color=#0000ff>new</font> Stack();
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < months.length; i++)
stk.push(months[i] + <font color=#004488>" "</font>);
System.out.println(<font color=#004488>"stk = "</font> + stk);
<font color=#009900>// Treating a stack as a Vector:</font>
stk.addElement(<font color=#004488>"The last line"</font>);
System.out.println(
<font color=#004488>"element 5 = "</font> + stk.elementAt(5));
System.out.println(<font color=#004488>"popping elements:"</font>);
<font color=#0000ff>while</font>(!stk.empty())
System.out.println(stk.pop());
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Each line in the <B>months
</B>array is inserted into the <B>Stack</B> with <B>push( )</B>, and later
fetched from the top of the stack with a <B>pop( )</B>. To make a point,
<B>Vector </B>operations are also performed on the <B>Stack</B> object. This is
possible because, by virtue of inheritance, a <B>Stack</B> <I>is</I> a
<B>Vector</B>. Thus, all operations that can be performed on a <B>Vector</B> can
also be performed on a <B>Stack</B>, such as
<B>elementAt( )</B>.</FONT><A NAME="_Toc375545357"></A><A NAME="_Toc408018573"></A><BR></P></DIV>
<A NAME="Hea
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -