📄 tij313.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">
<!--
This document was converted from RTF source:
By r2net 5.8 r2netcmd Windows
See http://www.logictran.com
-->
<head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Thinking in Java, 3rd ed. Revision 4.0: 11: Collections of Objects</title>
<link rel="stylesheet" href="stylesheet.css" type="text/css"></head>
<body >
<CENTER> <a href="http://www.MindView.net"> <img src="mindview.gif" alt="MindView Inc." BORDER = "0"></a> <Font FACE="Verdana, Tahoma, Arial, Helvetica, Sans"> <h2>Thinking in Java, 3<sup>rd</sup> ed. Revision 4.0</h2> <FONT size = "-1"><br> [ <a href="README.txt">Viewing Hints</a> ] [ <a href="http://www.mindview.net/Books/TIJ/">Book Home Page</a> ] [ <a href="http://www.mindview.net/Etc/MailingList.html">Free Newsletter</a> ] <br> [ <a href="http://www.mindview.net/Seminars">Seminars</a> ] [ <a href="http://www.mindview.net/CDs">Seminars on CD ROM</a> ] [ <a href="http://www.mindview.net/Services">Consulting</a> ] <br><br> </FONT></FONT> </CENTER>
<font face="Georgia"><div align="CENTER"><a href="TIJ312.htm" target="RightFrame"><img src="./prev.gif" alt="Previous " border="0"></a>
<a href="TIJ314.htm" target="RightFrame"><img src="./next.gif" alt="Next " border="0"></a>
<a href="TIJ3_t.htm"><img src="./first.gif" alt="Title Page " border="0"></a>
<a href="TIJ3_i.htm"><img src="./index.gif" alt="Index " border="0"></a>
<a href="TIJ3_c.htm"><img src="./contents.gif" alt="Contents " border="0"></a>
</div>
<hr>
<h1>
<a name="_Toc24272650"></a><a name="_Toc24775733"></a><a name="Heading10173"></a>11:
Collections of <br>Objects</h1>
<p class="Intro">It’s a fairly simple program that has only a fixed quantity of objects with known lifetimes.<br></p>
<p>In general, your programs will always be creating new objects based on some criteria that will be known only at the time the program is running. You won’t know until run time the quantity or even the exact type of the objects you need. To solve the general programming problem, you need to be able to create any number of objects, anytime, anywhere. So you can’t rely on creating a named reference to hold each one of your objects:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>MyObject myReference;</PRE></FONT></BLOCKQUOTE><p><br></p>
<p>since you’ll never know how many of these you’ll actually need. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap09_1248" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Most languages provide some way to solve this rather essential problem. Java has several ways to hold objects (or rather, references to objects). The built-in type is the array, which has been discussed before. Also, the Java utilities library has a reasonably complete set of <a name="Index955"></a><i>container classes</i> (also known as <a name="Index956"></a><i>collection</i> <i>classes</i>, but because the Java 2 libraries use the name <b>Collection</b> to refer to a particular subset of the library, I shall also use the more inclusive term “container”). Containers provide sophisticated ways to hold and even manipulate your objects. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap09_1249" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h2>
<a name="_Toc375545347"></a><a name="_Toc24775734"></a><a name="Heading10180"></a>Arrays</h2>
<p>Most of the necessary introduction to arrays is in the last section of Chapter 4, which showed how you define and initialize an array. Holding objects is the focus of this chapter, and an array is just one way to hold objects. But there are a number of other ways to hold objects, so what makes an array special? <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap09_1250" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p><a name="Index957"></a>There are three issues that distinguish arrays from other types of containers: efficiency, type, and the ability to hold primitives. The array is the most efficient way that Java provides to store and randomly access a sequence of object references. The array is a simple linear sequence, which makes element access fast, but you pay for this speed; when you create an array object, its size is fixed and cannot be changed for the lifetime of that array object. You might suggest creating an array of a particular size and then, if you run out of space, creating a new one and moving all the references from the old one to the new one. This is the behavior of the <a name="Index958"></a><a name="Index959"></a><b>ArrayList </b>class, which will be studied later in this chapter. However, because of the overhead of this flexibility, an <b>ArrayList</b> is measurably less efficient than an array. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap09_1251" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>In C++, the <a name="Index960"></a><b>vector</b> container class <i>does</i> know the type of objects it holds, but it has a different drawback when compared with arrays in Java: The C++ <b>vector</b>’s <b>operator[]</b> doesn’t do bounds checking, so you can run past the end.<sup><a name="fnB51" href="#fn51">[51]</a></sup> In Java, you get bounds checking regardless of whether you’re using an array or a container; you’ll get a <a name="Index961"></a><b>RuntimeException</b> if you exceed the bounds. This type of exception indicates a programmer error, and thus you don’t need to check for it in your code. As an aside, the reason the C++ <b>vector</b> doesn’t check bounds with every access is speed; in Java, you have the constant performance overhead of bounds checking all the time for both arrays and containers. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap09_1252" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>The other generic container classes that will be studied in this chapter, <a name="Index962"></a><b>List</b>, <a name="Index963"></a><b>Set</b>, and <a name="Index964"></a><b>Map</b>, all deal with objects as if they had no specific type. That is, they treat them as type <a name="Index965"></a><b>Object</b>, the root class of all classes in Java. This works fine from one standpoint: You need to build only one container, and any Java object will go into that container. (Except for primitives, which can be placed in containers as constants using the Java primitive wrapper classes, or as changeable values by wrapping in your own class.) This is the second place where an array is superior to the generic containers: When you create an array, you create it to hold a specific type (which is related to the third factor—an array can hold primitives, whereas a container cannot). This means that you get compile-time type checking to prevent you from inserting the wrong type or mistaking the type that you’re extracting. Of course, Java will prevent you from sending an inappropriate message to an object at either compile time or run time. So it’s not riskier one way or the other, it’s just nicer if the compiler points it out to you, faster at run time, and there’s less likelihood that the end user will get surprised by an exception. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap09_1253" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>For efficiency and type checking, it’s always worth trying to use an array. However, when you’re solving a more general problem, arrays can be too restrictive. After looking at arrays, the rest of this chapter will be devoted to the container classes provided by Java. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap09_1254" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h3>
<a name="_Toc375545348"></a><a name="_Toc24775735"></a><a name="Heading10187"></a>Arrays
are first-class objects<br></h3>
<p><a name="Index966"></a><a name="Index967"></a>Regardless of what type of array you’re working with, the array identifier is actually a reference to a true object that’s created on the heap. This is the object that holds the references to the other objects, and it can be created either implicitly, as part of the array initialization syntax, or explicitly with a <b>new</b> expression. Part of the array object (in fact, the only field or method you can access) is the read-only <b>length</b> member that tells you how many elements can be stored in that array object. <a name="Index968"></a><a name="Index969"></a>The ‘<b>[]</b>’ syntax is the only other access that you have to the array object. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap09_1255" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>The following example shows the various ways that an array can be initialized, and how the array references can be assigned to different array objects. It also shows that arrays of objects and arrays of primitives are almost identical in their use. The only difference is that arrays of objects hold references, but arrays of primitives hold the primitive values directly. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap09_1256" title="Send BackTalk Comment">Feedback</a></font><br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c11:ArraySize.java</font>
<font color=#009900>// Initialization & re-assignment of arrays.</font>
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;
<font color=#0000ff>class</font> Weeble {} <font color=#009900>// A small mythical creature</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> ArraySize {
<font color=#0000ff>private</font> <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
<font color=#009900>// Arrays of objects:</font>
Weeble[] a; <font color=#009900>// Local uninitialized variable</font>
Weeble[] b = <font color=#0000ff>new</font> Weeble[5]; <font color=#009900>// Null references</font>
Weeble[] c = <font color=#0000ff>new</font> Weeble[4];
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < c.length; i++)
<font color=#0000ff>if</font>(c[i] == <font color=#0000ff>null</font>) <font color=#009900>// Can test for null reference</font>
c[i] = <font color=#0000ff>new</font> Weeble();
<font color=#009900>// Aggregate initialization:</font>
Weeble[] d = {
<font color=#0000ff>new</font> Weeble(), <font color=#0000ff>new</font> Weeble(), <font color=#0000ff>new</font> Weeble()
};
<font color=#009900>// Dynamic aggregate initialization:</font>
a = <font color=#0000ff>new</font> Weeble[] {
<font color=#0000ff>new</font> Weeble(), <font color=#0000ff>new</font> Weeble()
};
System.out.println(<font color=#004488>"a.length="</font> + a.length);
System.out.println(<font color=#004488>"b.length = "</font> + b.length);
<font color=#009900>// The references inside the array are</font>
<font color=#009900>// automatically initialized to null:</font>
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < b.length; i++)
System.out.println(<font color=#004488>"b["</font> + i + <font color=#004488>"]="</font> + b[i]);
System.out.println(<font color=#004488>"c.length = "</font> + c.length);
System.out.println(<font color=#004488>"d.length = "</font> + d.length);
a = d;
System.out.println(<font color=#004488>"a.length = "</font> + a.length);
<font color=#009900>// Arrays of primitives:</font>
<font color=#0000ff>int</font>[] e; <font color=#009900>// Null reference</font>
<font color=#0000ff>int</font>[] f = <font color=#0000ff>new</font> <font color=#0000ff>int</font>[5];
<font color=#0000ff>int</font>[] g = <font color=#0000ff>new</font> <font color=#0000ff>int</font>[4];
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < g.length; i++)
g[i] = i*i;
<font color=#0000ff>int</font>[] h = { 11, 47, 93 };
<font color=#009900>// Compile error: variable e not initialized:</font>
<font color=#009900>//!System.out.println("e.length=" + e.length);</font>
System.out.println(<font color=#004488>"f.length = "</font> + f.length);
<font color=#009900>// The primitives inside the array are</font>
<font color=#009900>// automatically initialized to zero:</font>
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < f.length; i++)
System.out.println(<font color=#004488>"f["</font> + i + <font color=#004488>"]="</font> + f[i]);
System.out.println(<font color=#004488>"g.length = "</font> + g.length);
System.out.println(<font color=#004488>"h.length = "</font> + h.length);
e = h;
System.out.println(<font color=#004488>"e.length = "</font> + e.length);
e = <font color=#0000ff>new</font> <font color=#0000ff>int</font>[] { 1, 2 };
System.out.println(<font color=#004488>"e.length = "</font> + e.length);
monitor.expect(<font color=#0000ff>new</font> String[] {
<font color=#004488>"a.length=2"</font>,
<font color=#004488>"b.length = 5"</font>,
<font color=#004488>"b[0]=null"</font>,
<font color=#004488>"b[1]=null"</font>,
<font color=#004488>"b[2]=null"</font>,
<font color=#004488>"b[3]=null"</font>,
<font color=#004488>"b[4]=null"</font>,
<font color=#004488>"c.length = 4"</font>,
<font color=#004488>"d.length = 3"</font>,
<font color=#004488>"a.length = 3"</font>,
<font color=#004488>"f.length = 5"</font>,
<font color=#004488>"f[0]=0"</font>,
<font color=#004488>"f[1]=0"</font>,
<font color=#004488>"f[2]=0"</font>,
<font color=#004488>"f[3]=0"</font>,
<font color=#004488>"f[4]=0"</font>,
<font color=#004488>"g.length = 4"</font>,
<font color=#004488>"h.length = 3"</font>,
<font color=#004488>"e.length = 3"</font>,
<font color=#004488>"e.length = 2"</font>
});
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>The array <b>a</b> is an uninitialized local variable, and the compiler prevents you from doing anything with this reference until you’ve properly initialized it. The array <b>b</b> is initialized to point to an array of <b>Weeble</b> references, but no actual <b>Weeble</b> objects are ever placed in that array. However, you can still ask what the size of the array is, since <b>b</b> is pointing to a legitimate object. This brings up a slight drawback: You can’t find out how many elements are actually <i>in</i> the array, since <b>length</b> tells you only how many elements <i>can</i> be placed in the array; that is, the size of the array object, not the number of elements it actually holds. However, when an array object is created, its references are automatically initialized to <b>null</b>, so you can see whether a particular array slot has an object in it by checking to see whether it’s <b>null</b>. Similarly, an array of primitives is automatically initialized to zero for numeric types, <b>(char)0 </b>for <b>char</b>, and<b> false</b> for <b>boolean</b>. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap09_1257" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Array <b>c</b> shows the creation of the array object followed by the assignment of <b>Weeble</b> objects to all the slots in the array. Array <b>d</b> shows the “aggregate initialization” syntax that causes the array object to be created (implicitly with <b>new</b> on the heap, just like for array <b>c</b>) <i>and</i> initialized with <b>Weeble</b> objects, all in one statement. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap09_1258" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p><a name="Index972"></a><a name="Index973"></a>The next array initialization could be thought of as a “dynamic aggregate initialization.” The aggregate initialization used by <b>d</b> must be used at the point of <b>d</b>’s definition, but with the second syntax you can create and initialize an array object anywhere. For example, suppose <b>hide( )</b> is a method that takes an array of <b>Weeble</b> objects. You could call it by saying:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>hide(d);</PRE></FONT></BLOCKQUOTE><p><br></p>
<p>but you can also dynamically create the array you want to pass as the argument:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>hide(<font color=#0000ff>new</font> Weeble[] { <font color=#0000ff>new</font> Weeble(), <font color=#0000ff>new</font> Weeble() });</PRE></FONT></BLOCKQUOTE><p><br></p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -