JAVA 数组 官方文档说明http://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html
转自 http://blog.sina.com.cn/s/blog_62b8fc330100p5ol.html
4.5
数组是编程语言中最常见的一种数据结构,它可用于存储多个数据,一个数据被称为数组元素,通常可通过数组元素的索引来访问数组元素,包括为数组元素赋值和取出数组元素的数据。Java语言的数组则具有它特有的特征,下面将详细介绍Java语言的数组。
4.5.1
Java的数组要求所有数组元素具有相同的数据类型。因此,在一个数组中,数组元素的类型是唯一的,即一个数组里只能存储一种数据类型的数据,而不能存储多种数据类型的数据。
因为Java语言是面向对象的语言,能很好地支持类与类之间的继承关系,这样可能产生一个数组里可以存放多种数据类型的假象:例如有一个水果数组,要求每个数组元素都是水果,实际上数组元素既可是苹果,也可以是香蕉,但这个数组的数组元素的类型还是唯一的,只能是水果类型。
一旦数组的初始化完成,数组在内存中所占的空间将被固定下来,因此数组的长度将不可改变。即使把某个数组元素的数据清空,但它所占的空间依然被保留,依然属于该数组,数组的长度依然不变。
Java的数组既可以存储基本类型的数据,也可以存储引用数据类型的数据。只要所有数组元素具有相同类型即可。
值得指出的是:数组也是一种数据类型,它本身是一种引用类型。例如int是一个基本类型,但int[](这是定义数组的一种方式)就是一种引用类型了。
学生提问:int[]是一种类型吗?怎么使用这种类型呢?
答:没错,int[]就是一种数据类型,与int类型、String类型类似,一样可以使用该类型来定义变量,也可以使用该类型进行类型转换等,使用int[]类型来定义变量、进行类型转换时与使用其他普通类型没有任何区别。int[]类型是一种引用类型,创建int[]类型的对象时也就是创建数组,则需要使用创建数组的语法。
4.5.2 定义数组
4.5.2
Java语言支持两种语法格式来定义数组:
type[] arrayName; |
对这两种语法格式而言,通常推荐使用第一种格式。因为第一种格式不仅具有更好的语意,也具有更好的可读性:对于type[] arrayName;方式,很容易理解这是定义一个变量,其中变量名是arrayName,而变量类型是type[],前面已经指出:type[]确实是一种新类型,与type类型完全不同(例如int类型是基本类型,但int[]是引用类型)。因此,这种方式既容易理解,也符合定义变量的语法。但第二种格式:type arrayName[]的可读性就差了,看起来好像定义了一个类型为type的变量,而变量名是arrayName[],这与真实的含义相去甚远。
可能有些读者非常喜欢type arrayName[];这种定义数组的方式,这可能是因为早期某些计算机读物的误导,从现在开始就不要再使用这种糟糕的方式了。
C#就不再支持type arrayName[]这种语法,它只支持第一种定义数组的语法。越来越多的语言不再支持type arrayName[]这种数组定义语法。
数组是一种引用类型的变量,因此使用它定义一个变量时,仅仅表示定义了一个引用变量(也就是定义了一个指针),这个引用变量还未指向任何有效的内存,因此定义数组时不能指定数组的长度。而且由于定义数组仅仅只是定义了一个引用变量,并未指向任何有效的内存空间,所以还没有内存空间来存储数组元素,因此这个数组也不能使用,只有对数组进行初始化后,才可以使用。
定义数组时不能指定数组的长度。
4.5.3 数组的初始化
4.5.3
Java语言中数组必须先初始化,然后才可以使用。所谓初始化,就是为数组的数组元素分配内存空间,并为每个数组元素赋初始值。
学生提问:能不能只分配内存空间,不赋初始值呢?
答:不行!一旦为数组的每个数组元素分配了内存空间,每个内存空间里存储的内容就是该数组元素的值,即使这个内存空间存储的内容是空,这个空也是一个值(null)。不管以哪种方式来初始化数组,只要为数组元素分配了内存空间,数组元素就具有了初始值,初始值的获得有两种形式:一种由系统自动分配,一种由程序员指定。
数组的初始化有两种方式:
静态初始化:初始化时由程序员显式指定每个数组元素的初始值,由系统决定需要的数组长度。
动态初始化:初始化时程序员只指定数组长度,由系统为数组元素分配初始值。
静态初始化
静态初始化的语法格式如下:
arrayName = new type[]{element1, element2 , element3 , element4 ...} |
在上面的语法格式中,前面的type就是数组元素的数据类型,此处的type必须与定义数组变量时所使用的type相同,也可以是定义数组时所使用的type的子类;并使用花括号把所有的数组元素括起来,多个数组元素之间以英文逗号(,)隔开,定义初始化值的花括号紧跟[]之后。值得指出的是:执行静态初始化时,显式指定的数组元素值的类型必须与new关键字后type类型相同,或者是其子类的实例。下面代码定义使用了这三种形式类进行静态初始化:
程序清单:codes/04/4-5/TestArray.java |
因为Java语言是面向对象的编程语言,能很好地支持子类和父类的继承关系:子类实例是一种特殊的父类实例。在上面程序中,String类型是Object类型的子类,即字符串是一种特殊的Object实例。关于继承更详细的介绍,请参考本书第5章。
除此之外,静态初始化还有如下简化的语法格式:
arrayName = {element1, element2 , element3 , element4 ...} |
在这种语法格式中,直接使用花括号来定义一个数组,花括号把所有数组元素括起来形成一个数组。
实际开发过程中,可能更习惯将数组定义和数组初始化同时完成,如下代码(程序清单同上):
//数组的定义和初始化同时完成,使用简化的静态初始化写法 |
动态初始化
动态初始化只指定数组的长度,由系统为每个数组元素指定初始值,动态初始化的语法格式如下:
arrayName = new type[length]; |
在上面语法中,需要指定一个int整型的length参数,这个参数指定了数组的长度,也就是可以容纳数组元素的个数。与静态初始化相似的,此处的type必须与定义数组时使用的type类型相同,或者是定义数组时使用的type类型的子类。下面代码示范了如何进行动态初始化(程序清单同上):
//数组的定义和初始化同时完成,使用动态初始化语法 |
执行动态初始化时,程序员只需指定数组的长度,即为每个数组元素指定所需的内存空间,系统将负责为这些数组元素分配初始值。指定初始值时,系统按如下规则分配初始值:
数组元素的类型是基本类型中的整数类型(byte、short、int和long),则数组元素的值是0。
数组元素的类型是基本类型中的浮点类型(float、double),则数组元素的值是0.0。
数组元素的类型是基本类型中的字符类型(char),则数组元素的值是'\u0000'。
数组元素的类型是基本类型中的布尔类型(boolean),则数组元素的值是false。
数组元素的类型是引用类型(类、接口和数组),则数组元素的值是null。
不要静态初始化和动态初始化同时使用,也就是说不要在进行数组初始化时,既指定数组的长度,也为每个数组元素分配初始值。
数组初始化完成后,就可以使用数组了,包括为数组元素赋值,访问数组元素值和获得数组长度等。
http://book.51cto.com/art/200809/89190.htm
4.5.4 使用数组
4.5.4
数组最常用的用法就是访问数组元素,包括对数组元素进行赋值和访问数组元素的值,访问数组元素都是通过在数组引用变量后紧跟一个方括号([]),方括号里是数组元素的索引值,这样就可以访问数组元素了。访问到数组元素后,就可以把一个数组元素当成一个普通变量使用,包括为该变量赋值和取出该变量的值,这个变量的类型就是定义数组时使用的类型。
值得指出的是,Java语言的数组索引是从0开始的,也就是说,第一个数组元素的索引值为0,最后一个数组元素的索引为数组长度减1。下面代码示范输出数组元素的值,以及为指定数组元素赋值(程序清单同上):
//输出objArr数组的第二个元素,将输出字符串"李刚" |
如果访问数组元素时指定的索引小于0,或者大于等于数组的长度,编译程序不会出现任何错误,将运行时出现异常:java.lang.ArrayIndexOutOfBoundsExc
//访问数组元素指定的索引等于数组长度,所以下面代码将在运行时出现异常 |
学生提问:为什么要我记住这些异常信息?
答:编写一个程序,并不是独指在电脑里敲出这些代码,还包括调试这个程序,使之可以正常运行。没有任何人可以保证自己写的程序总是正确的,因此调试程序是写程序的重要组成部分,调试程序的工作量往往超过编写代码的工作量。如果根据错误提示信息,准确定位错误位置,并排除程序错误是程序员的基本功。培养这些基本功需要记住常见异常信息,以及其对应的出错原因。
所有数组都提供了一个length属性,通过这个属性可以访问到数组的长度,一旦获得了数组的长度后,就可以通过循环来遍历该数组的每个数组元素,下面代码示范了输出prices数组(动态初始化的int[]数组)的每个元素的值(程序清单同上):
//使用循环输出pricese数组的每个数组元素的值 |
执行上面代码将输出5个0,因为prices数组执行的是默认初始化,因为数组元素是int类型,系统为int类型的数组元素赋值为0。
下面代码将示范为动态初始化的数组元素进行赋值,并通过循环方式输出每个数组元素(程序清单同上):
//对动态初始化后的数组元素进行赋值 |
上面代码将先输出字符串"Struts2权威指南"和"轻量级J2EE企业应用实战",然后输出两个null,因为books使用了动态初始化,系统为所有数组元素都分配一个null作为初始值,后来程序又为前两个元素赋值,所以看到程序的输出结果。
从上面代码中不难看出,初始化一个数组后,相当于同时初始化了多个相同类型的变量,通过数组元素的索引就可以自由访问这些变量(实际上都是数组元素)。使用数组元素与使用普通变量并没有什么不同,一样可以对数组元素进行赋值,或者取出数组元素的值。