您的位置:首页 > 其它

第11章 持有对象

2016-04-29 19:36 323 查看
如果一个程序只包含固定数量的且其生命周期都是已知的对象,那么这是一个非常简单的程序

通常,程序总是根据运行时才知道的某些条件去创建新对象,在此之前,不会知道所需对象的数量,甚至不知道确切的类型。未解决这个普通的编程问题,需要在任意时刻和任意位置创建任意数量的对象。所以,就不能依靠创建命名的引用来持有每一个对象。

因为你不知道实际上会需要多少这样的引用。

大多数语言都提供某种方法来解决这个基本问题。Java有多种方式保存对象(应该说是对象的引用)。例如前面曾经学习过的数组,它是编译器支持的类型。数组是保存一组对象的最有效的方式,如果你想保存一组基本类型数据,也推荐使用这种方式。但是数组具有固定的尺寸,而在更一般的情况中,你在写程序时并不知道将需要多少个对象,或者是否需要更负责的方式来存储对象,你在写程序时并不知道将需要多少个对象,或者是需要更复杂的方式来存储对象,因此数组尺寸固定这一限制显得过于受限了。

Java实用类库还提供了一套相当完整的容器类来解决这个问题,其中基本的类型是List、Set、Queue和Map。这些对象类型也称为集合类,但由于Java的类库中使用了Collection这个名字来指代该类库的一个特殊子集,

import java.util.ArrayList;

public class ApplesAndOrangesWithoutGenerics {

public static void main(String[] args) {
ArrayList apples = new ArrayList();
for (int i = 0; i < 3; i++) {
apples.add(new Apple());
apples.add(new Orange());
}
for (int i = 0; i < apples.size(); i++) {
((Apple) apples.get(i)).id();
}
}
}


11.1 泛型和类型安全的容器

使用Java SE5之前的容器的一个主要问题就是编译器允许你向容器中插入不正确的类型。例如,考虑一个Apple对象的容器,我们使用最基本最可靠的容器ArrayList

练习1:(2)创建一个新类Gerbil(沙鼠),包含int gerbilNumber,在构造器中初始化它(类似于本章的Mouse示例)。添加一个方法hop(),用以打印沙鼠的号码以及它正在跳跃的信息。创建一个ArrayList,并向其中添加一串Gerbil对象。使用get()遍历List,并且对每个Gerbil调用hop()

import java.util.ArrayList;

public class Gerbil {
private int gerbilNumber;

public int getGerbilNumber() {
return gerbilNumber;
}

public void setGerbilNumber(int gerbilNumber) {
this.gerbilNumber = gerbilNumber;
}

public Gerbil(int gerbilNumber) {
setGerbilNumber(gerbilNumber);
}

public void hop() {
System.out.println("gerbilNumber==" + gerbilNumber);
}

public static void main(String[] args) {
ArrayList<Gerbil> list = new ArrayList<Gerbil>();
list.add(new Gerbil(1));
list.add(new Gerbil(2));
list.add(new Gerbil(3));
list.add(new Gerbil(4));

for (int i = 0; i < list.size(); i++) {
Gerbil gerbil = list.get(i);
if (gerbil == null) {
continue;
}
gerbil.hop();
}
}
}


11.2 基本概念

Java容器类类库的用途是”保存对象“,并将其划分为不同的概念:

1) Collection。一个独立元素的序列,这些元素都服从一条或多条规则。List必须按照插入的顺序保存元素,而Set不能有重复元素。Queue按照牌堆规则来确定对象产生的顺序(通常与它们被插入的顺序相同)。

2) Map。一组成对的”键值对“对象,允许你使用键来查找值。ArrayList允许你使用数字来查找值,因此在某种意义上讲,它将数字与对象关联在了一起。映射表允许我们使用另一个对象来查找某个对象,

尽管并非总是这样,但是在理想情况下,你编写的大部分代码都是在与这些接口打交道,并且你唯一需要制定所使用的精确类型的地方就是在创建的时候。因此,你可以像下面这样创建一个List

List<Apple> apples = new ArrayList<Apple>();


Collection接口概括了序列的概念—–一种存放一组对象的方式。下面这个简单的示例用Integer对象填充了一个Collection()

import java.util.ArrayList;
import java.util.Collection;

public class SimpleCollection {
public static void main(String[] args) {
Collection<Integer> c = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
c.add(i);
}
for (Integer i : c) {
System.out.print(i + ", ");
}
}
}


因为这个示例只使用了Collection方法,因此任何继承自Collection的类的对象都可以正常工作,但是ArrayList是最基本的序列类型。

所有的Collection都可以用foreach语法遍历

练习2:(1)修改SimpleCollection.java,使用Set来表示c

import java.util.LinkedHashSet;

import java.util.Set;

public class SimpleCollection {
public static void main(String[] args) {
Set<Integer> c = new LinkedHashSet<Integer>();
for (int i = 0; i < 10; i++) {
c.add(i);
}
for (Integer i : c) {
System.out.print(i + ", ");
}
}
}


练习3:(2)修改innerclasses/Sequence.java,使你可以向其中添加任意数量的元素。

11.3 添加一组元素

java.util包中的ArraysCollections类中有很多实用方法,可以在一个Collection中添加一组元素。Arrays.asList()方法

11.6 迭代器

任何容器类,都必须有某种方式可以插入元素并将它们再次取回。毕竟,持有事务是容器最基本的工作。对于Listadd()是插入元素的方法之一,而get()是去除元素的方法之一。

如果从更高层的角度思考,会发现这里有个缺点:要使用容器,必须对容器的确切类型编程。初看起来这没什么不好,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: