《Android游戏开发详解》——第2章,第2.21节对象和基本类型的分组
本节书摘来自异步社区《Android游戏开发详解》一书中的第2章,第2.21节对象和基本类型的分组,作者 【美】Jonathan S. Harbour,更多章节内容可以访问云栖社区“异步社区”公众号查看
2.21 对象和基本类型的分组
Android游戏开发详解
Java允许我们把对象和基本类型组织到一起。我们常见的有两种对象,可以用来进行分组,它们是数组和列表。
2.21.1 数组
要表示某种类型的一个数组(或组),我们使用方括号。例如,如果想要整数的一个数组,可以像下面这样声明。
int[] numbers = new int[5];
上面例子中的数字5,表示名为numbers的数组应该有多大。正如上面所声明的,numbers将能够容纳5个整数值。要描述数组的样子,我们可以画一个表,如图2-28所示。
一开始,数组将会有默认值(创建整数数组的时候,默认值是0)。Java允许我们直接为每个索引(或位置)分配数值。数组索引是基于0的,就像字符串中的字符一样。数组的赋值语法如下所示。
numbers[0] = 5; numbers[1] = 10; numbers[2] = 15; numbers[3] = 20; numbers[4] = 25;
numbers数组将会如图2-29所示。
我们可以使用完全相同的语法来获取这些值。举例如下。
int sum = numbers[0] + numbers[1] + numbers[2] + numbers[3] + numbers[4]; System.out.println(sum) // will print 75
数组也有缺点。一旦创建了数组,就不能改变其大小。为什么会有这个问题呢?想象一下,你在开发一个射击游戏,其中每次玩家点击鼠标左键,就会有一个Bullet对象添加到一个数组中(表示所有已经发射的子弹)。我们事先不知道需要多少个Bullet。某些玩家可能使用42颗子弹。其他的玩家可能使用刀和手榴弹,甚至不开一枪就完成了关卡。在这种情况下,使用ArrayList通常会更好,它允许我们动态地调整大小以放入更多的对象。
2.21.2 ArrayLists
ArrayLists比数组更加常用,并且你应该知道如何使用它们(以及如何用好它们)。要使用ArrayList,必须首先导入它。
import java.util.ArrayList 创建ArrayLists,就像创建任何其他的对象一样。 ArrayList playerNames = new ArrayList(); 我们使用add()方法向一个ArrayList对象中插入对象。 playerNames.add(“Mario”); playerNames.add(“Luigi”); ... playerNames.add(“Yoshi”); 你可以看到,这是String对象的一个ArrayList。你可以调用get()方法,使用基于0的索引(注意,用于数组的[]对于ArrayLists无效)从一个ArrayList获取一个对象(在这个例子中,是一个String对象)。 playerNames.get(2); // will retrieve “Luigi” (kind-of) 理论上讲,我们可以在一个单个的ArrayList中,放置所有的各种类型的对象,而不管其类型是什么;然而,这不是很有用,因为一旦你这么做了,可能不知道某个位置(如索引152)具体是什么类型的对象。如果不知道它是什么类型的对象,你就不知道它有什么方法。看如下所示的例子。 someArrayList.get(152); // What kind of object is this?
我们从someArrayList提取出第153个对象(记住,索引是基于0的)。问题在于,我们对这个对象一无所知。它可能是一个可口的Sushi对象,又或者甚至是一个危险的Bomb。如果我们这样编写代码,想象一下后果。
Monster hungryOne = new Monster(); Object unknown = someArrayList.get(152); // The Object is actually a Bomb hungryOne.eat(unknown); // hungryOne thinks it’s Sushi // Boom!
实际上,Java允许我们通过添加标志,来限制ArrayLists只保存某一种类型的对象。
ArrayList<String> playerNames = new ArrayList<String>(); playerNames.add(“Mario”); // Works! Bomb b = new Bomb(); playerNames.add(b); // Gives type-mismatch error
现在,我们知道从playerNames获取的任何对象都是一个String,并且我们可以在其上调用String方法。
// Any object from playerNames will always be a String String nameZero = playerNames.get(0); System.out.println(nameZero.length());
2.21.3 对基本类型使用ArrayList
不能直接将基本数据类型插入到一个ArrayList中。实际上,如下所示的代码是不允许的。
ArrayList<int> numbers = new ArrayList<int>(); // not allowed
要绕开这个限制,可以直接使用一个内建的包装类,即每种基本数据类型的对象版本。这包括int所对应的Integer,char所对应的Character,等等。要做到这点,直接创建该ArrayList并声明包装类作为其类型。
ArrayList<Integer> numbers = new ArrayList<Integer>();
这个ArrayList最初的大小为0。
System.out.println(numbers.size()); // Prints zero
接下来,直接调用add()方法,并且传入想要放到ArrayList中的int值。这些值将会自动地包装到一个Integer对象中。
numbers.add(2); numbers.add(3); numbers.add(1);
此时,ArrayList看上去如图2-30所示(注意,其长度动态地增长了)。
你可以调用get()方法,传入想要的值的索引,从而获取基本类型值。例如,要取回数字3,让ArrayList给出位于索引1的值。这个值会自动转换为一个int(从包装的Integer对象),因此,你可以将它存储到一个int变量中。
``
int myNum = numbers.get(1);
System.out.println(myNum); // Prints 3
**2.21.4 对ArrayList使用循环** 在亲眼见到ArrayList的应用之前,你很难认识到它有多么强大,因此,让我们来尝试一个例子。 我们将编写包含了2个类的一个简单的程序。第一个类是我们的进入点,其中,我们存储了main方法并且创建了ArrayList。第二个类将是表示人的一个定制类。 首先,创建一个名为Groups的、新的Java项目。其中,创建一个名为ListTester的新的类,并且给其一个main方法,如程序清单2.25所示。 程序清单2.25 ListTester.java
01 public class ListTester {
02
03 public static void main(String[] args) {
04
05 }
06
07 }
现在,在同一项目中创建第二个类并将其命名为Person。添加如下所示的变量和方法(参见程序清单2.26)。 程序清单2.26 Person.java
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(更新版本)
1 public class ListTester { 2 3 public static void main(String[] args) { 4 Person p = new Person(); 5 p.initialize("Marty", 40); 6 p.describe(); 7 } 8 9 }
我们来一行一行地看一看程序清单2.27:首先创建了Person类的一个名为p的新实例。此时,p有两个实例变量:name和age。这些变量还没有初始化。
接下来,我们调用了initialize()方法,它接受两个值:一个String和一个整数。initialize()方法将会接受这两个值,并且将其赋值给实例变量。
现在,两个实例变量已经初始化了,我们可以通过调用describe()来要求Person对象描述自己。结果如下所示。
My name is Marty I am 40 years old
现在,我们创建多个Person对象并且将它们组织到一个ArrayList中。修改ListTester类,使其如程序清单2.28所示。
程序清单2.28 创建ArrayList并添加第一个循环
01 import java.util.ArrayList; 02 import java.util.Random; 03 04 public class ListTester { 05 06 public static void main(String[] args) { 07 08 ArrayList<Person> people = new ArrayList<Person>(); 09 Random r = new Random(); 10 11 for (int i = 0; i < 5; i++) { 12 Person p = new Person(); 13 p.initialize("Person #" + i, r.nextInt(50)); 14 people.add(p); 15 } 16 } 17 18 }
在程序清单2.28中,我们创建了一个新的、名为people的ArrayList,以及一个新的名为r的Random对象。然后,开始了一个for循环,它将运行5次。循环每迭代(重复)一次,我们就创建一个名为p的新的Person对象。用相应的名称(Person #i,其中i从0到4)和一个随机生成的年龄值,来为该Person初始化实例变量。最后,我们把新创建的Person对象添加到ArrayList中(第14行)。循环重复,创建了一个全新的Person,初始化它并且再次添加它。
注意如下所示的代码行。
Person p = new Person();
在循环中创建的任何变量,都只在其相同的迭代中有效,这意味着,该变量仅限于在循环的当前迭代中存在。因此,我们可以在循环的每一次重复中复用变量名p。
每次调用上面的代码,我们都用变量名p创建了一个新的Person。然后,将临时变量p中保存的值,存储到较为持久的、名为people的ArrayList中,以便随后在代码中可以引用每一个新创建的Person对象,而不需要为它们中的每一个分配一个唯一的变量名。
为了看到这是如何工作的,我们可以尝试再次迭代循环,并且调用describe()方法,如程序清单2.29所示(第17行到第20行)。
程序清单2.29 添加第2个循环
01 import java.util.ArrayList; 02 import java.util.Random; 03 04 public class ListTester { 05 06 public static void main(String[] args) { 07 08 ArrayList<Person> people = new ArrayList<Person>(); 09 Random r = new Random(); 10 11 for (int i = 0; i < 5; i++) { 12 Person p = new Person(); 13 p.initialize("Person #" + i, r.nextInt(50)); 14 people.add(p); 15 } 16 17 for (int i = 0; i < people.size(); i++) { 18 Person p = people.get(i); 19 p.describe(); 20 } 21 22 } 23 24 }
最终的输出如下所示(年龄可能不同,因为是随机生成的)。
My name is Person #0 I am 29 years old My name is Person #1 I am 1 years old My name is Person #2 I am 4 years old My name is Person #3 I am 21 years old My name is Person #4 I am 47 years old
你可能会问,为什么要将第17行到第20行的循环运行people.size()次而不是5次?两个值是相同的,并且任何一个解决方案都会产生相同的输出;然而,上面的例子是一个更加灵活的循环,因为它并不需要把循环运行的次数直接编码。根据ArrayList people的大小,第二个for循环将运行相应的次数。这意味着,我们可能需要将上一个循环(即向ArrayList添加对象的那个循环)运行的次数从5修改为8,而下面的循环则不需要修改,因为people.size()也会增加为8。
程序清单2.30 迭代8次
01 import java.util.ArrayList; 02 import java.util.Random; 03 04 public class ListTester { 05 06 public static void main(String[] args) { 07 08 ArrayList<Person> people = new ArrayList<Person>(); 09 Random r = new Random(); 10 11 //for (int i = 0; i < 5; i++) { 12 for (int i = 0; i < 8; i++) { 13 Person p = new Person(); 14 p.initialize("Person #" + i, r.nextInt(50)); 15 people.add(p); 16 } 17 // people.size() is now 8! 18 for (int i = 0; i < people.size(); i++) { 19 Person p = people.get(i); 20 p.describe(); 21 } 22 23 } 24 25 }
最终输出如下所示(年龄可能不同,因为是随机生成的)。
My name is Person #0 I am 27 years old My name is Person #1 I am 27 years old My name is Person #2 I am 20 years old My name is Person #3 I am 28 years old My name is Person #4 I am 5 years old My name is Person #5 I am 49 years old My name is Person #6 I am 2 years old My name is Person #7 I am 26 years old
上面的示例展示了如何使用循环快速地创建多个对象,并将它们组织到一个ArrayList中。我们还学习到,可以通过一个for循环快速遍历一个ArrayList的所有成员并调用其方法。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
《Android 应用案例开发大全(第二版)》——6.2节Intent对象
本节书摘来自异步社区《Android 应用案例开发大全(第二版)》一书中的第6章,第6.2节Intent对象,作者李宁,更多章节内容可以访问云栖社区“异步社区”公众号查看 6.2 Intent对象Android开发权威指南(第二版)上一节介绍了Intent的主要作用就是封装和传递各种信息。那么Intent对象到底可以封装和传递哪些信息呢?本节将会揭开这些秘密。 6.2.1 Intent对象可以封装和传递哪些信息Intent对象可以封装和传递如下6种信息。 组件名(Component name)。动作(Action)。种类(Category)。数据(Data)。附加信息(Extra)。标志(Flags)。在6.2.1至6.2.7小节会分别介绍这6种信息,并从6.4节开始提供大量的案例演示在Android应用中如何使用这些信息。 6.2.2 组件名(Component name)Intent对象可以直接指定要访问的组件,例如,有一个名为MyActivity的窗口类,可以使用下面的代码指定该窗口类。 // 下面的代码在窗口类中调用,this就是Context对象 Intent intent ...
- 下一篇
《Android 应用案例开发大全(第二版)》——6.3节显式和隐式访问窗口
本节书摘来自异步社区《Android 应用案例开发大全(第二版)》一书中的第6章,第6.3节显式和隐式访问窗口,作者李宁,更多章节内容可以访问云栖社区“异步社区”公众号查看 6.3 显式和隐式访问窗口Android开发权威指南(第二版)到现在为止读者已经见识过大量的Android应用程序,这些应用大多都有两个或两个以上的窗口,这就要求在某一个窗口中显示另外一个窗口。想必读者已经观察到不同显示窗口的方式。我们最开始接触到直接指定窗口类的方式称为显式访问窗口,而后来的一些程序,尤其是上一章调用系统窗口的例子又向我们展示了另外一种访问窗口的方式:隐式访问窗口。 显式访问窗口不会产生歧义,系统可以毫不犹豫地显示指定的窗口,下面是一段典型的显式访问窗口的代码。 Intent intent = new Intent(this, MyActivity.class); startActivity(intent); 隐式访问窗口与显式访问窗口不同,前者并不需要指定窗口类的class,而只需要指定与窗口绑定的字符串(Action、Category和Data),至于如何设置Intent对象,要看访问的窗口在...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Red5直播服务器,属于Java语言的直播服务器
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长