1第五章数组5.1数组数组(array)是相同类型数据的集合体,可以使用共同的名字引用它。数组可被定义为任何类型,可以是一维或多维。数组中的元素是通过下标来访问它。数组提供了一种将有联系的信息分组的便利方法。在数组创建的时候它的长度也随之定义。5.1.1创建和使用一维数组一维数组(one-dimensionalarray)实质上是相同类型变量列表。要创建一个数组,必须首先定义数组变量所需的类型。通用的一维数组的声明格式是:typevar-name[];其中,type定义了数组的基本类型。基本类型决定了组成数组的每一个基本元素的数据类型。这样,数组的基本类型决定了数组存储的数据类型。例如,下面的例子定义了数据类型为int,名为week的数组。intweek[];尽管该例子定义了week是一个数组变量的事实,但实际上没有数组变量存在。事实上,week的值被设置为空,它代表一个数组没有值。为了使数组week成为实际的、物理上存在的整型数组,必须用运算符new来为其分配地址并且把它赋给week。运算符new是专门用来分配内存的运算符。当运算符new被应用到一维数组时,它的一般形式如下:typearray_att=newtype[size];其中,type指定被分配的数据类型,size指定数组中变量的个数,array_att是被链接到数组的数组变量。也就是,使用运算符new来分配数组,必须指定数组元素的类型和数组元素的个数。用运算符new分配数组后,数组中的元素将会被自动初始化。下面的例子分配了一个10个整型元素的数组并把它们和数组anArray链接起来。anArray=newint[10];通过这个语句的执行,数组anArray将会指向10个整数,而且数组中的所有元素将被初始化为零。例5.1:publicclassArrayDemo{publicstaticvoidmain(String[]args){int[]anArray;//declareanarrayofintegersanArray=newint[10];//createanarrayofintegers//assignavaluetoeacharrayelementandprintfor(inti=0;ianArray.length;i++){anArray[i]=i;System.out.print(anArray[i]+);2}System.out.println();}}让我们回顾一下上面的过程:获得一个数组需要2步。第一步,定义变量所需的类型。第二步,使用运算符new来为数组所要存储的数据分配内存,并把它们分配给数组变量。这样Java中的数组被动态地分配。一旦分配了一个数组,可以在方括号内指定它的下标来访问数组中特定的元素。所有的数组下标从零开始。例如,下面的语句将值5赋给数组week的第二个元素。week[1]=5;下面的程序显示存储在下标为3的数组元素中的值。System.out.println(week[3]);下面程序定义的数组存储了每月的天数。例5.2:classArray{publicstaticvoidmain(Stringargs[]){intmonth_days[];month_days=newint[12];month_days[0]=31;month_days[1]=28;month_days[2]=31;month_days[3]=30;month_days[4]=31;month_days[5]=30;month_days[6]=31;month_days[7]=31;month_days[8]=30;month_days[9]=31;month_days[10]=30;month_days[11]=31;System.out.println(Aprilhas+month_days[5]+days.);}}当运行这个程序时,它打印出6月份的天数。如前面提到的,Java数组下标从零开始,因此6月份的天数数组元素为month_days[5]或30。将对数组变量的声明和对数组本身的分配结合起来是可以的,如下所示:intmonth_days[]=newint[12];数组可以在声明时被初始化。这个过程和简单类型初始化的过程一样。数组的初始化(arrayinitializer)就是包括在花括号之内用逗号分开的表达式的列表。逗号分开了数组元素的值。Java会自动地分配一个足够大的空间来保存指定的初始化元素的个数,而不必使用运算符new。例如,为了存储每月中的天数,下面的程序定义了一个初始化的整数数组:例5.3:classAutoArray{publicstaticvoidmain(Stringargs[]){intmonth_days[]={31,28,31,30,31,30,31,31,30,31,30,31};System.out.println(Aprilhas+month_days[3]+days.);}}当运行这个程序时,它和前一个程序产生的输出一样。Java严格地检查以保证用户不会意外地去存储或引用在数组范围以外的值。Java的运行系统会检查以确保所有的数组下标都在正确的范围以内(在这方面,Java与C/C++从根本上不同,C/C++不提供运行边界检查)。例如,运行系统将检查数组month_days的每个下标的值以保证它包括在0和11之间。如果企图访问数组边界以外(负数或比数组边界大)的元素,将引起运行错误。3下面的例子运用一维数组来计算用户输入数字的平均数。例5.4://Averageanarrayofvalues.publicclassAverage{publicstaticvoidmain(Stringargs[]){doubleinputN[]=newdouble[args.length];for(inti=0;iargs.length;i++){inputN[i]=Double.parseDouble(args[i]);}doubleaccount=0;for(intj=0;jargs.length;j++){account+=inputN[j];}System.out.println(平均值是:+account/args.length);}};5.1.2多维数组在Java中,多维数组(multidimensionalarrays)实际上是数组的数组。定义多维数组变量要将每个维数放在它们各自的方括号中。例如,下面语句定义了一个名为twoD的二维数组变量。inttwoD[][]=newint[4][5];该语句分配了一个4行5列的数组并把它分配给数组twoD。实际上这个矩阵表示了int类型的数组的数组被实现的过程。下列程序从左到右,从上到下为数组的每个元素赋值,然后显示数组的值:例5.5:classTwoDArray{publicstaticvoidmain(Stringargs[]){inttwoD[][]=newint[4][5];inti,j,k=0;for(i=0;i4;i++)for(j=0;j5;j++){twoD[i][j]=k;k++;}for(i=0;i4;i++){for(j=0;j5;j++)System.out.print(twoD[i][j]+);System.out.println();}}4}程序运行的结果如下:012345678910111213141516171819当给多维数组分配内存时,只需指定第一个(最左边)维数的内存即可。可以单独地给余下的维数分配内存。例如,下面的程序在数组twoD被定义时给它的第一个维数分配内存,对第二维则是手工分配地址。inttwoD[][]=newint[4][];twoD[0]=newint[5];twoD[1]=newint[5];twoD[2]=newint[5];twoD[3]=newint[5];尽管在这种情形下单独地给第二维分配内存没有什么优点,但在其他情形下就不同了。例如,当手工分配内存时,不需要给每个维数相同数量的元素分配内存。如前面所说,既然多维数组实际上是数组的数组,每个数组的维数在控制之下。例如,下列程序定义了一个二维数组,它的第二维的大小是不相等的。例5.6://Manuallyallocatedifferingsizeseconddimensions.classTwoDAgain{publicstaticvoidmain(Stringargs[]){inttwoD[][]=newint[4][];twoD[0]=newint[1];twoD[1]=newint[2];twoD[2]=newint[3];twoD[3]=newint[4];inti,j,k=0;for(i=0;i4;i++)for(j=0;jtwoD[i][j]=k;k++;}for(i=0;i4;i++){for(j=0;jSystem.out.print(twoD[i][j]+);System.out.println();}}}该程序产生的输出如下:01234556789该程序定义的数组可以表示如下:对于大多数应用程序,我们不推荐使用不规则多维数组,因为它们的运行与人们期望的相反。但是,不规则多维数组在某些情况下使用效率较高。例如,如果需要一个很大的二维数组,而它仅仅被稀疏地占用(即其中一维的元素不是全被使用),这时不规则数组可能是一个完美的解决方案。初始化多维数组是可能的。初始化多维数组只不过是把每一维的初始化列表用它自己的大括号括起来即可。下面的程序产生一个矩阵,该矩阵的每个元素包括数组下标的行和列的积。同时注意在数组的初始化中可以像用字面量一样用表达式。例5.7:classMatrix{publicstaticvoidmain(Stringargs[]){doublem[][]={{0*0,1*0,2*0,3*0},{0*1,1*1,2*1,3*1},{0*2,1*2,2*2,3*2},{0*3,1*3,2*3,3*3}};inti,j;for(i=0;i4;i++){for(j=0;j4;j++)System.out.print(m[i][j]+);System.out.println();}}}当运行这个程序时,将得到下面的输出:0.00.00.00.00.01.02.03.00.02.04.06.00.03.06.09.0正如看到,数组中的每一行就像初始化表指定的那样被初始化。让我们再看一个使用多维数组的例子。下面的程序首先产生一个3×4×5的3维数组,然后装入用它的下标之积生成的每个元素,最后显示了该数组。例5.8://Demonstrateathree-dimensionalarray.classthreeDMatrix{publicstaticvoidmain(Stringargs[]){intthreeD[][][]=newint[3][4][5];inti,j,k;for(i=0;i3;i++)for(j=0;j4;j++)for(k=0;k5;k++)threeD[i][j][k]=i*j*k;for(i=0;i3;i++){6for(j=0;j4;j++){for(k=0;k5;k++)System.out.print(threeD[i][j][k]+);System.out.println();}System.out.println();}}}该程序的输出如下:000000000000000000000000001234024680369120000002468048121606121824另外声明数组还有第二种格式:type[]var-name;这里,方括号紧跟在类型标识符type的后面,而不是跟在数组变量名的后面。例如,下面的两个定义是等价的:intal[]=newint[3];int[]a2=newint[3];下面的两个定义也是等价的:chartwod1[][]=newchar[3][