本节书摘来自异步社区《android游戏开发详解》一书中的第2章,第2.21节对象和基本类型的分组,作者 【美】jonathan s. harbour,更多章节内容可以访问云栖社区“异步社区”公众号查看
2.21 对象和基本类型的分组
android游戏开发详解
java允许我们把对象和基本类型组织到一起。我们常见的有两种对象,可以用来进行分组,它们是数组和列表。
2.21.1 数组
要表示某种类型的一个数组(或组),我们使用方括号。例如,如果想要整数的一个数组,可以像下面这样声明。
上面例子中的数字5,表示名为numbers的数组应该有多大。正如上面所声明的,numbers将能够容纳5个整数值。要描述数组的样子,我们可以画一个表,如图2-28所示。

一开始,数组将会有默认值(创建整数数组的时候,默认值是0)。java允许我们直接为每个索引(或位置)分配数值。数组索引是基于0的,就像字符串中的字符一样。数组的赋值语法如下所示。
numbers数组将会如图2-29所示。
我们可以使用完全相同的语法来获取这些值。举例如下。
数组也有缺点。一旦创建了数组,就不能改变其大小。为什么会有这个问题呢?想象一下,你在开发一个射击游戏,其中每次玩家点击鼠标左键,就会有一个bullet对象添加到一个数组中(表示所有已经发射的子弹)。我们事先不知道需要多少个bullet。某些玩家可能使用42颗子弹。其他的玩家可能使用刀和手榴弹,甚至不开一枪就完成了关卡。在这种情况下,使用arraylist通常会更好,它允许我们动态地调整大小以放入更多的对象。
2.21.2 arraylists
arraylists比数组更加常用,并且你应该知道如何使用它们(以及如何用好它们)。要使用arraylist,必须首先导入它。
我们从somearraylist提取出第153个对象(记住,索引是基于0的)。问题在于,我们对这个对象一无所知。它可能是一个可口的sushi对象,又或者甚至是一个危险的bomb。如果我们这样编写代码,想象一下后果。
实际上,java允许我们通过添加标志,来限制arraylists只保存某一种类型的对象。
现在,我们知道从playernames获取的任何对象都是一个string,并且我们可以在其上调用string方法。
2.21.3 对基本类型使用arraylist
不能直接将基本数据类型插入到一个arraylist中。实际上,如下所示的代码是不允许的。
要绕开这个限制,可以直接使用一个内建的包装类,即每种基本数据类型的对象版本。这包括int所对应的integer,char所对应的character,等等。要做到这点,直接创建该arraylist并声明包装类作为其类型。
这个arraylist最初的大小为0。
接下来,直接调用add()方法,并且传入想要放到arraylist中的int值。这些值将会自动地包装到一个integer对象中。
此时,arraylist看上去如图2-30所示(注意,其长度动态地增长了)。
你可以调用get()方法,传入想要的值的索引,从而获取基本类型值。例如,要取回数字3,让arraylist给出位于索引1的值。这个值会自动转换为一个int(从包装的integer对象),因此,你可以将它存储到一个int变量中。
``
int mynum = numbers.get(1);
system.out.println(mynum); // prints 3
01 public class listtester {
02
03 public static void main(string[] args) {
04
05 }
06
07 }
01 public class person {
02
03 private string name;
04 private int age;
05
06 public void initialize(string name, int age) {
07 this.name = name;
08 this.age = age;
09 }
10
11 public void describe() {
12 system.out.println("my name is " + name);
13 system.out.println("i am " + age + " years old");
14 }
15
16 }
person类描述了一个新的person对象的蓝图。特别是,它表明了一个person对象的状态将由两个实例变量来描述,即name和age。我们没有给name和age默认值,并且,必须调用initialize()方法来提供这些值。一旦person对象有了一个name和age,我们就可以调用describe()方法,以易于理解、可读的形式打印出这些信息。让我们回到listtester并且确保可以做到这一点。
程序清单2.27 listtester.java(更新版本)
我们来一行一行地看一看程序清单2.27:首先创建了person类的一个名为p的新实例。此时,p有两个实例变量:name和age。这些变量还没有初始化。
接下来,我们调用了initialize()方法,它接受两个值:一个string和一个整数。initialize()方法将会接受这两个值,并且将其赋值给实例变量。
现在,两个实例变量已经初始化了,我们可以通过调用describe()来要求person对象描述自己。结果如下所示。
现在,我们创建多个person对象并且将它们组织到一个arraylist中。修改listtester类,使其如程序清单2.28所示。
程序清单2.28 创建arraylist并添加第一个循环
在程序清单2.28中,我们创建了一个新的、名为people的arraylist,以及一个新的名为r的random对象。然后,开始了一个for循环,它将运行5次。循环每迭代(重复)一次,我们就创建一个名为p的新的person对象。用相应的名称(person #i,其中i从0到4)和一个随机生成的年龄值,来为该person初始化实例变量。最后,我们把新创建的person对象添加到arraylist中(第14行)。循环重复,创建了一个全新的person,初始化它并且再次添加它。
注意如下所示的代码行。
在循环中创建的任何变量,都只在其相同的迭代中有效,这意味着,该变量仅限于在循环的当前迭代中存在。因此,我们可以在循环的每一次重复中复用变量名p。
每次调用上面的代码,我们都用变量名p创建了一个新的person。然后,将临时变量p中保存的值,存储到较为持久的、名为people的arraylist中,以便随后在代码中可以引用每一个新创建的person对象,而不需要为它们中的每一个分配一个唯一的变量名。
为了看到这是如何工作的,我们可以尝试再次迭代循环,并且调用describe()方法,如程序清单2.29所示(第17行到第20行)。
程序清单2.29 添加第2个循环
最终的输出如下所示(年龄可能不同,因为是随机生成的)。
你可能会问,为什么要将第17行到第20行的循环运行people.size()次而不是5次?两个值是相同的,并且任何一个解决方案都会产生相同的输出;然而,上面的例子是一个更加灵活的循环,因为它并不需要把循环运行的次数直接编码。根据arraylist people的大小,第二个for循环将运行相应的次数。这意味着,我们可能需要将上一个循环(即向arraylist添加对象的那个循环)运行的次数从5修改为8,而下面的循环则不需要修改,因为people.size()也会增加为8。
程序清单2.30 迭代8次
最终输出如下所示(年龄可能不同,因为是随机生成的)。
上面的示例展示了如何使用循环快速地创建多个对象,并将它们组织到一个arraylist中。我们还学习到,可以通过一个for循环快速遍历一个arraylist的所有成员并调用其方法。