数组的定义
Java语言支持两种语法格式来定义数组:
对这两种语法格式而言,通常推荐使用第一种格式。因为第一种格式不仅具有更好的语意,而且具有更好的可读性。对于type[]
arrayName;方式,很容易理解这是定义一个变量,其中变量名是arrayName,而变量类型是type[]。
type[]确实是一种
新类型,与type类型完全不同(例如int类型是基本类型,但int[]是
引用类型)。因此,这种方式既容易理解,也符合定义变量的语法。
但第二种格式type arrayName[]的可读性就差了,看起来好像定义了
一个类型为type的变量,而变量名是arrayName[],这与真实的含义相
去甚远。
数组是一种引用类型的变量,因此使用它定义一个变量时,仅仅表示定义了一个引用变量(也就是定义了一个指针),这个引用变量 还未指向任何有效的内存,因此定义数组时不能指定数组的长度。而 且由于定义数组只是定义了一个引用变量,并未指向任何有效的内存 空间,所以还没有内存空间来存储数组元素,因此这个数组也不能使 用,只有对数组进行初始化后才可以使用。
注意:定义数组时不能指定数组的长度。
数组的初始化
Java语言中数组必须先初始化,然后才可以使用。所谓初始化,就是为数组的数组元素分配内存空间,并为每个数组元素赋初始值。
一旦为数组的每个数组元素分配了内存空间,每个内存空
间里存储的内容就是该数组元素的值,即使这个内存空间存储的内容
是空,这个空也是一个(null)。不管以哪种方式来初始化数组,
只要为数组元素分配了内存空间,数组元素就具有了初始值。初始值
的获得有两种形式:一种由系统自动分配;另一种由程序员指定。
静态初始化的语法格式如下:
arrayName = new type[] {element1,element2,element3...}
在上面的语法格式中,前面的type就是数组元素的数据类型,此处的type必须与定义数组变量时所使用的type相同,也可以是定义数
组时所指定的type的子类,并使用花括号把所有的数组元素括起来,
多个数组元素之间以英文逗号(
,)隔开,定义初始化值的花括号紧跟
[]之后。值得指出的是,执行静态初始化时,显式指定的数组元素值
的类型必须与new关键字后的type类型相同,或者是其子类的实例。下
面代码定义了使用这三种形式来进行静态初始化
因为Java语言是面向对象的编程语言,能很好地支持子类和父类的继承关系:子类实例是一种特殊的父类实例。在上面程序中,
String类型是Object类型的子类,即字符串是一种特殊的Object实
例。
除此之外,静态初始化还有如下简化的语法格式:
在这种语法格式中,直接使用花括号来定义一个数组,花括号把所有的数组元素括起来形成一个数组。只有在定义数组的同时执行数
组初始化才支持使用简化的静态初始化。
在实际开发过程中,可能更习惯将数组定义和数组初始化同时完
成,代码如下
2.动态初始化
动态初始化只指定数组的长度,由系统为每个数组元素指定初始值。动态初始化的语法格式如下:
在上面语法中,需要指定一个int类型的length参数,这个参数指定了数组的长度,也就是可以容纳数组元素的个数。与静态初始化相
似的是,此处的type必须与定义数组时使用的type类型相同,或者是
定义数组时使用的type类型的子类。下面代码示范了如何进行动态初
始化
执行动态初始化时,程序员只需指定数组的长度,即为每个数组元素指定所需的内存空间,系统将负责为这些数组元素分配初始值。
指定初始值时,系统按如下规则分配初始值。
➢
数组元素的类型是基本类型中的整数类型(byte、short、int和long),则数组元素的值是0。
➢
数 组 元 素 的 类 型 是 基 本 类 型 中 的 浮 点 类 型 ( float 、double),则数组元素的
值是0.0。
➢
数组元素的类型是基本类型中的字符类型(char),则数组元素的值是'\u0000'。
➢
数组元素的类型是基本类型中的布尔类型(boolean),则数组元素的值是false。
➢
数组元素的类型是引用类型(类、接口和数组),则数组元素的值是null。
注意:不要同时使用静态初始化和动态初始化,也就是说,不要在进行数组初始化时,既指定数组的长度,也为每个数组元素分配初始 值
foreach循环
从Java 5之后,Java提供了一种更简单的循环:foreach循环,这种循环遍历数组和集合(关于集合的介绍请参考本书第8章)更加简
洁。使用foreach循环遍历数组和集合元素时,无须获得数组和集合长
度,无须根据索引来访问数组元素和集合元素,foreach循环自动遍历
数组和集合的每个元素。
foreach循环的语法格式如下:
在上面语法格式中,type是数组元素或集合元素的类型,或者直接使用var定义,variableName是一个形参名,foreach循环将自动将 数组元素、集合元素依次赋给该变量。下面程序示范了如何使用 foreach循环来遍历数组元素。从上面程序可以看出,使用foreach循环遍历数组元素时无须获得数组长度,也无须根据索引来访问数组元素。foreach循环和普通循环 不同的是,它无须循环条件,无须循环迭代语句,这些部分都由系统 来完成,foreach循环自动迭代数组的每个元素,当每个元素都被迭代一次后,foreach循环自动结束。 对于foreach循环而言,循环变量的类型可由编译器自动推断出 来,而且使用var定义也不会降低程序的可读性,因此建议使用var来 声明循环变量的类型。所以,将上面的粗体字代码改为如下形式会更 加简洁
当使用foreach循环来迭代输出数组元素或集合元素时,通常不要对循环变量进行赋值,虽然这种赋值在语法上是允许的,但没有太大 的实际意义,而且极容易引起错误。例如下面程序
运行上面程序,将看到如下运行结果:
从上面的运行结果来看,由于在foreach循环中对数组元素进行赋值,结果导致不能正确遍历数组元素,不能正确地取出每个数组元素 的值。而且当再次访问第一个数组元素时,发现数组元素的值依然没 有改变。不难看出,当使用foreach来迭代访问数组元素时,foreach 中的循环变量相当于一个临时变量,系统会把数组元素依次赋给这个 临时变量,而这个临时变量并不是数组元素,它只是保存了数组元素 的值。因此,如果希望改变数组元素的值,则不能使用这种foreach循 环。 注意: 使用foreach循环迭代数组元素时,并不能改变数组元素的值, 因此不要对foreach的循环变量进行