System.out.println(a[i]);
}
}
图5-2程序运行结果
4.特殊的一维数组-命令行参数
在Java应用程序中我们必须写publicstaticvoidmain(String[]args)主方法。
main方法中有一个参数是字符串数组args,这个数组的元素args[0],args[1]……args[n]的值都是字符串。
args就是命令行的参数。
在Java解释器解释用户的字节码文件时,可以包括需要传给main方法的参数。
一般形式为:
java类文件名字符串1字符串2……字符串n
其中,类文件名和各字符串间用空格分隔。
例如,在执行类Exam5_2时,命令行的输入是
JavacExam5_2goodbetterbest
这里,args[0]代表参数“good”,args[1]代表参数“better”,args[2]代表参数“best”,这时数组的长度为3。
【例5-2】命令行参数数组的使用
如图5-3所示,通过命令行参数输入若干内容,以倒序在屏幕上显示。
图5-3命令行参数程序运行结果
代码如下:
//Exam5_2.java
publicclassExam5_2{
voidrun(String[]a){
intn=a.length;
for(inti=n-1;i>=0;i--)
System.out.println(a[i]);
}
publicstaticvoidmain(Stringargs[]){
Exam5_2ee=newExam5_2();
ee.run(args);
}
}
程序分析:
由于要倒序显示,所以用for循环时,从下标最高的元素开始循环。
Java的数组在定义时要求定义数组的长度,但是这个字符串数组的长度是与用户输入的参数个数确定的,是不定的,所以这是一个特殊的一维数组。
5.对象数组
前面讨论的数组的数据类型都是简单的基本类型,即数组元素是简单数据类型。
但实际问题中往往需要把不同类型的数据组合成一个有机的整体,以便于引用。
例如,一名学生的姓名、性别、年龄和各科学习成绩等都与这名学生紧密相关,而一个班(乃至更多)的学生又都具有这些属性,如表所示。
如果将这些数据项定义为相互独立的简单变量是难以反映它们之间的内在联系的,应当将它们组织在一起形成一种数据结构。
这种数据结构在过去的结构化程序设计中被称为记录或结构体,而在面向对象的程序设计中把这种结构也称为对象。
由自定义的对象作为数组元素所构成的数组被称为对象数组,也就是说,对象数组是指数组的每一个元素都是具有相同属性的对象,或者说,如果一个类有若干个对象,我们可以把这一系列同类的对象用一个数组来存放。
如表5-1所示学生情况表,可用一个对象数组来存放。
表5-1学生情况表
编号
姓名
性别
入学成绩
20050701001
李小平
男
490
20050701002
张华
男
530
20050702003
孙晓月
女
470
20050702004
王明明
女
513
20050702005
刘玉
女
469
20050703006
周丽萍
女
487
20050703007
李军
男
532
……
……
……
……
【例5_3】参考表5-1学生情况表,要求将每个学生作为一个对象,建立输出对象的全部数据成员的成员方法stuDisp()。
代码如下:
//Student.java
classStudent
{privateStringname;
privatecharsex;
privatedoublescore;
Student(Stringcname,charcsex,doublecscore)
{name=cname;
sex=csex;
score=cscore;
}
voidstudPrint()
{System.out.println("Name:
"+name+"\tSex:
"+sex+"\tScore:
"+score);}
}
//Exam5_3.java
publicclassExam5_3{
voidrun(){
Studentstu[]=newStudent[7];
stu[0]=newStudent("20050701001","李小平","男",490);
stu[1]=newStudent("20050701002","张华","男",530);
stu[2]=newStudent("20050702003","孙晓月","女",470);
stu[3]=newStudent("20050702004","王明明","女",513);
stu[4]=newStudent("20050702005","刘玉","女",469);
stu[5]=newStudent("20050703006","周丽萍","女",487);
stu[6]=newStudent("20050703007","李军","男",532);
intn=stu.length;
for(inti=n-1;i>=0;i--)
stu[i].stuDisp();
}
publicstaticvoidmain(Stringargs[]){
Exam5_3ee=newExam5_3();
ee.run();
}
}
程序运行结果如下:
图5-4对象数组的使用
程序分析:
本程序用了两个类,类Student包含四个成员变量,同时还包含一个能显示这些成员变量的成员方法stuDisp()。
类Exam5_3定义了一个Student类型的数组,给每个数组元素分别赋值,然后利用成员方法stuDisp()显示成员变量的内容。
5.1.2二维数组
Java中只有一维数组,不存在称为“二维数组”的明确结构。
但是如果一个一维数组的数组元素可以是数组,这样就构成了Java语言的二维数组。
也就是说,在Java语言中,把二维数组实际上看成是其每个数组元素是一个一维数组的一维数组。
一个3行4列的二维数组的形式如图5-5所示。
图5-5二维数组
计算机存储器的编址是一维的,即存储单元的编号从0开始一直连续编到最后一个最大的编号。
如图5-6所示矩阵,如果用二维数组表示,则在计算机中的存放形式如图5-7所示。
图5-6矩阵图5-7二维数组在Java中的实现
在图5-7中把每一行看成一个数组元素,则有三行的数组可看成只有三个数组元素,只不过这三个元素又是由三个元素组成的。
1.二维数组的声明
二维数组的声明与一维数组类似,只是需要给出两对方括号,其格式如下:
类型说明符数组名[][];
或
类型说明符[][]数组名;
例如:
intarr[][];
或int[][]arr;
其中:
类型说明符可以是Java的基本类型、类或接口;数组名是用户遵循标识符命名规则给出的一个标识符;两个方括号中前面的方括号表示行,后面的方括号表示列。
2.二维数组的初始化
二维数组声明同样也是为数组命名和指定其数据类型的。
它不为数组元素分配内存,只有经初始化后才能为其分配存储空间。
二维数组的初始化也分为直接指定初值和用new操作符两种方式。
(1)用new操作符初始化数组
用new操作符来初始化数组有两种方式:
第一种:
先声明数组再初始化数组。
在数组已经声明以后,可用下述两种格式中的任意一种来初始化二维数组。
数组名=new类型说明符[数组长度][];
或
数组名=new类型说明符[数组长度][数组长度];
其中:
对数组名、类型说明符和数组长度的要求与一维数组一致。
例如:
intarra[][];//声明二维数组
arra=newint[3][4];//初始化二维数组
上述两条语句声明并创建了一个3行4列的数组arra。
也就是说arra数组有3个元素,而每一个元素又都是长度为4的一维数组。
实际上共有12个元素,共占用12*4=48个字节的连续存储空间。
这里的语句:
arra=newint[3][4];
实际上相当于下述4条语句:
arra=newint[3][];创建一个有3个元素的数组,且每个元素也是一个数组。
arra[0]=newint[4];创建arra[0]元素的数组,它有4个元素。
arra[1]=newint[4];创建arra[1]元素的数组,它有4个元素。
arra[2]=newint[4];创建arra[2]元素的数组,它有4个元素。
也等价于:
arra=newint[3][]
for(inti=0;i<3;i++){arra[i]=newint[4];}
也就是说,在初始化二维数组时也可以只指定数组的行数而不给出数组的列数,每一行的长度由二维数组引用时决定。
但不能只指定列数而不指定行数。
上述语句的作用如图5-8所示。
图5-8二维数组的初始化
第二种:
在声明数组时初始化数组。
格式如下:
类型说明符[][]数组名=new类型说明符[数组长度][];
或
类型说明符数组名[][]=new类型说明符[数组长度][数组长度];
例如:
int[][]arr=newint[4][];
intarr[][]=newint[4][3];
可以不指定列数只指定行数,但是,不指定行数而指定列数是错误的。
例如,下面的初始化是错误的。
int[][]arr=newint[][4];
(2)直接指定初值的方式
在数组声明时对数据元素赋初值就是用指定的初值对数组初始化。
例如
int[][]arr1={{3,-9,6},{8,0,1},{11,9,8}};
声明并初始化数组arr1,它有3个元素,每个元素又都是有3个元素的一维数组。
用指定初值的方式对数组初始化时,各子数组元素的个数可以不同。
例如:
int[][]arr1={{3,-9},{8,0,1},{10,11,9,8}};
它等价于:
int[][]arr1=newint[3][];
intar1[0]={3,-9};
intar1[1]={8,0,1};
intar1[2]={10,11,9,8};
也等价于:
int[][]arr1=newint[3][];
intarb1[0]={3,-9};
intarb1[1]={8,0,1};
intarb1[2]={10,11,9,8};
arr1[0]=arb1[0];//实际上是将一个一维数组赋给了一个二维数组的元素,下同
arr1[1]=arb1[1];
arr1[2]=arb1[2];
3.二维数组的长度及数组赋值
与一维数组一样,也可以用.length成员方法测定二维数组的长度,即元素的个数。
只不过当使用“数组名.length”的形式测定的是数组的行数;而使用“数组名[i].length”的形式测定的是该行的列数。
例如,若有如下的初始化语句:
int[][]arr1={{3,-9},{8,0,1},{10,11,9,8}};
则arr1.length的返回值是3,表示数组arr1有3行或3个元素。
而arr1[2].length的返回值是4,表示arr1[2]的长度为4,即有4个元素。
【例5_4】将如图5-6所示矩阵的数据赋值给一个二维数组a,计算每行数字的和,将其存放到一个一维数组b中。
代码如下:
//Exam5_4.java
publicclassExam5_4{
voidrun(){
inti,j;
intb[]=newint[3];
inta[][]={{25,53,89},{28,66,90},{10,38,56}};
for(i=0;i<3;i++){
b[i]=0;
for(j=0;j<3;j++)
b[i]=b[i]+a[i][j];
}
for(i=0;i<3;i++)
System.out.println(b[i]);
}
publicstaticvoidmain(Stringargs[]){
Exam5_4ee=newExam5_4();
ee.run();
}
}
程序运行结果如下:
图5-9二维数组的使用
三维数组或更多维数组的使用方法和二维数组的使用方法类同。
由于Java语言的二维数组是由一维数组定义,所以,可以把二维数组中的每个一维数组定义为不同的元素个数,这样就可以构成不规则的二维数组。
感兴趣的读者朋友可以查阅相应的参考书,本书不再多加介绍。
5.2字符串
每一种程序设计语言都离不开字符串的处理,在Java中是通过String类来实现相关操作。
字符串是由n(n>=0)个字符组成的序列。
Java中的字符串用一对双引号括起来,一个字符串中的字符个数称作字符串的长度。
如“jinan”就是一个长度为5,值为jinan的字符串。
我们在第二章中学到了字符的概念,读者朋友一定注意字符串与字符的区分。
字符常量是用单引号括起的单个字符,例如,'A','\n'等。
而字符串常量是用双引号括起的字符序列,例如,"A","\n","JavaNow"等。
在Java语言中,字符串常量通常是作为String类的对象而存在的,有专门的数据成员来表明它的长度。
本节主要讨论String类对象的创建、使用和操作。
5.2.1创建String对象
Java语言规定字符串常量必须用双引号括起,一个串可以包含字母、数字和各种特殊字符,如+、-、*、/、$等。
在我们前面的程序范例中已多次使用过字符串常量,例如下面的语句:
System.out.println("OK!
");
其中的"OK!
"就是字符串常量。
Java的任何字符串常量都是String类的对象,只不过在没有明确命名时,Java自动为其创建一个匿名String类的对象,所以,它们也被称为匿名String类的对象。
我们可以用下面的方法创建String类的对象。
例如:
Stringc1="Java";
本语句创建String类的对象c1,并通过赋值号将匿名String类的对象"Java"赋值给c1引用。
5.2.2String类的常用构造方法和常用方法
1.常用构造方法
String()
初始化一个新创建的String对象,它表示一个空字符序列。
String(byte[]bytes)
构造一个新的String,方法是使用平台的默认字符集解码字节的指定数组。
String(byte[]bytes,intoffset,intlength)
构造一个新的String,方法是使用指定的字符集解码字节的指定子数组。
String(byte[]bytes,intoffset,intlength,StringcharsetName)
构造一个新的String,方法是使用指定的字符集解码字节的指定子数组。
String(byte[]bytes,StringcharsetName)
构造一个新的String,方法是使用指定的字符集解码指定的字节数组。
String(char[]value)
分配一个新的String,它表示当前字符数组参数中包含的字符序列。
String(char[]value,intoffset,intcount)
分配一个新的String,它包含来自该字符数组参数的一个子数组的字符。
String(int[]codePoints,intoffset,intcount)
分配一个新的String,它包含该Unicode代码点数组参数的一个子数组的字符。
String(Stringoriginal)
初始化一个新创建的String对象,表示一个与该参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的一个副本。
String(StringBufferbuffer)
分配一个新的字符串,它包含当前包含在字符串缓冲区参数中的字符序列。
String(StringBuilderbuilder)
分配一个新