第5 章
显示班级成绩单 
学习目标
. 理解为什么使用数组; 
. 掌握应用数组进行程序设计; 
. 学习字符串类的常用方法。
5.1 示例程序
5.1.1 班级平均成绩 
第4章介绍了如何计算多个学生的平均成绩。如果想显示一个班学生的平均成绩和
每个人的成绩,这时就需要将输入的多个学生成绩进行保存。可以把多个学生的成绩保
存到一个数组中,然后进行计算并得到结果。程序代码如程序5.1所示。
【程序5.1】 程序StudentInfo.java。 
import java.util. Scanner; 
public class StudentInfo{ 
public static void main(String [] args){ 
final int SIZE = 5; 
double grade[] = new double[SIZE]; 
double averageGrade = 0; 
Scanner sc = new Scanner(System.in); 
for(int i=0; i<SIZE; i++){ 
grade[i] = sc.nextDouble(); 
} 
for(int i=0; i<SIZE; i++){ 
averageGrade = averageGrade + grade[i]; 
} 
averageGrade = averageGrade / SIZE; 
System.out.println("平均成绩:" + averageGrade); 
for(int i=0; i<SIZE; i++){ 
System.out.println("学生成绩:" + grade[i]); 
} 
} 
}

62 Java 基础与应用(第2 版) 
程序5.1的编译和运行结果如图5.1所示。程序5.1中定义了数组来保存学生的成
绩,数组定义语句如下: 
double grade[] = new double[SIZE]; 
定义double类型的数组grade,数组的长度为SIZE。需要注意的是数组不是基本类
型,而是引用类型,因此需要开辟数据的存储空间。newdouble[SIZE]的作用就是开辟数
组需要的存储空间,开辟空间的大小可以存放SIZE个double数值。每个数组元素占用
一个double类型数据的存储空间。上面定义的数组下标范围是0到SIZE-1,共计SIZE 
个元素,一般使用for循环来处理数组中的每一个元素。
图5.1 程序5.1运行结果
采用循环语句读入每个学生的成绩,语句grade[i]=sc.nextDouble()的作用是把读
入的双精度类型成绩数据存放到grade数组的第i个元素中,这样通过循环把所有的成绩
都读入到数组grade中。后面的计算和显示过程与前面的相似,循环将数组grade中的
元素累加求和,然后计算并输出平均成绩,最后也是通过循环显示数组grade中每个元素
的值。由于学生成绩保存在数组grade中,因此最后可以再次把学生成绩显示出来。
5.1.2 显示最高成绩
程序5.1显示了一个班的学生成绩,如果还想知道一个班学生的最高成绩是多少,并
把最高成绩显示出来,需要增加一段程序找到最高成绩。改进后的代码如程序5.2所示。
【程序5.2】 修改程序StudentInfo.java,显示最高成绩。 
import java.util. Scanner; 
public class StudentInfo{ 
public static void main(String [] args){ 
final int SIZE = 5; 
double grade[] = new double[SIZE]; 
double averageGrade = 0; 
double maxGrade = 0; 
Scanner sc = new Scanner(System.in);

第5 章 显示班级成绩单 63 
for(int i=0; i<SIZE; i++){ 
grade[i] = sc.nextDouble(); 
} 
maxGrade = grade[0]; 
for(int i=0; i<SIZE; i++){ 
averageGrade = averageGrade + grade[i]; 
if(maxGrade < grade[i]){ 
maxGrade = grade[i]; 
} 
} 
averageGrade = averageGrade / SIZE; 
System.out.println("平均成绩:" + averageGrade); 
System.out.println("最高成绩:" + maxGrade); 
for(int i=0; i<SIZE; i++){ 
System.out.println("学生成绩:" + grade[i]); 
} 
} 
} 
程序5.2的编译和运行结果如图5.2所示。
图5.2 程序5.2运行结果
找出数组中最大值的方法是,先假设第一个元素是最大的,把它放到变量maxGrade 
中,然后和数组中所有的元素逐一比较,如果发现比maxGrade大的元素,就把这个元素
放到maxGrade中。通过循环,对比数组中所有的元素,最后maxGrade中存放的值就是
数组中的最大值。
有的读者可能会想:是否可以将最大成绩maxGrade的初值设为0,逐个与学生成绩
进行比较,找到最大值。这个方法在本题中是可以的,但是不够安全,有的时候可能会出
问题。假设所有的学生成绩都是负的,这时候得到的最大值就有问题了。比较安全的方
法是把第一个成绩设置为最大值,然后进行比较。

64 Java 基础与应用(第2 版) 
5.2 相关知识
5.2.1 一维数组 
数组是用来存放一组相同类型数据的复合数据类型,常见的数组是一维数组,一维数
组声明的格式定义如下: 
数组元素类型数组名[ ]; 
或者: 
数组元素类型[ ] 数组名; 
例如程序5.2中定义数组doublegrade[],数组元素是double类型,数组名为grade。
数组定义后,还需要创建数组。创建数组就是为数组分配存储空间,使用关键字new 来
完成。例如程序5.2中的创建语句grade[]= newdouble[SIZE],创建一个有SIZE个
double类型元素的数组,数组的名字是grade。
通过下标来访问数组元素,例如程序5.2中的语句maxGrade=grade[i],读取grade 
的第i个元素,把它赋给变量maxGrade。
5.2.2 多维数组
同样,也可以定义二维数组或者是多维数组,二维数组的定义格式如下: 
数组元素类型数组名[ ][ ]; 
二维数组的创建方法也是相同的,例如doublegrade[][]= newdouble[5][6],表
示定义了一个具有5行6列的二维数组。使用二维数组元素的方式也与一维数组相同, 
通过下标来进行访问,例如: 
grade[3][4]=23.4,表示将数组grade的第3行第4列元素赋值为23.4。
Java程序中使用数组的情况相对C程序要少,多数情况下会使用集合类ArrayList 
来代替数组,有关集合类的定义和使用参见第21章。
5.2.3 String 类
第2章介绍了一种基本类型char,用于存储一个字符。如果程序中需要使用由多
个字符组成的字符串,就需要用到String类。例如,语句Stringname="张三";创建了
一个String类的对象name,值是字符串“张三”。创建字符串对象还可以使用String类
的构造方法来实现,例如Stringstr2=newString("Hello")。关于构造方法将在第8章
讲解。
字符串的常用操作包括字符串比较、求字符串长度、获取指定位置字符等,这些操作
都是通过调用String类的相应方法来实现,部分常用的方法如表5-1所示。

第5 章 显示班级成绩单 65 
表5-1 String类的方法
方 法 名功能简介
charcharAt(intindex) 返回字符串中第index个字符,索引index值从0开始计算
booleanequals(Stringstra) 判断当前字符串的内容是否与字符串stra内容相同,如相同返回
true,否则返回false 
intindexOf(Stringstra) 返回stra字符串在当前字符串中的索引位置,如果没有找到返回
-1 
intlength() 返回字符串的长度
Stringreplace(charoldChar,char 
newChar) 将当前字符串中所有oldChar字符替换为newChar 
Stringsubstring(intbeginIndex, 
intendIndex) 
返回字符串的子串,子串从beginIndex 开始,直到endIndex-1 
结束
StringtoLowerCase() 将字符串中所有大写字母变成小写
StringtoUpperCase() 将字符串中所有小写字母变成大写
Stringtrim() 去掉字符串两端的空格 
字符串的方法还有很多,如果想要了解更多的方法,可以查看String类的API文档。
表5-1中的方法是程序设计中最常用的方法。下面给出一个例子来演示字符串的使用, 
如程序5.3所示。
【程序5.3】 字符串常用方法示例。 
public class StringTest { 
public static void main(String[] args) { 
String s0 = "Program"; 
String s1 = "Java " + s0; //字符串连接 
String s2 = "Java program"; //注意p 小写 
String s3 = "Java Program"; //注意P 大写 
String s4 = "Java 程序设计"; 
//字符串比较 
System.out.println("----字符串比较----"); 
System.out.println("s1 和s2 的比较结果为" + s1.equals(s2)); 
System.out.println("s1 和s3 的比较结果为" + s1.equals(s3)); 
//字符串长度 
System.out.println("----字符串长度----"); 
System.out.println(s2.length( )); 
System.out.println(s4.length( )); 
//获取字符 
System.out.println("----获取字符----"); 
System.out.println(s1.charAt(0)); 
//字符替换 
System.out.println("----字符替换----");

66 Java 基础与应用(第2 版) 
System.out.println(s2.replace('J','j')); 
//大小写转换 
System.out.println("----大小写转换----"); 
System.out.println(s2.toUpperCase( )); 
System.out.println(s3.toLowerCase ( )); 
//子串查找 
System.out.println("----子串查找----"); 
System.out.println(s1.indexOf(s0)); 
System.out.println(s1.indexOf("a")); 
System.out.println(s1.indexOf("abc")); 
} 
} 
程序5.3的运行结果如图5.3所示。
图5.3 程序5.3运行结果
需要特别说明的是,比较两个字符串是否相等时,建议使用equals()方法,而不是使
用等号“==”,关于二者的区别将在第8章中讲解。
5.3 训练程序
输入一个班学生的成绩,先显示所有及格成绩,再显示所有不及格成绩;最后显示及
格人数和不及格人数。
5.3.1 程序分析
在程序5.1基础上来完成这个程序,同样还是使用数组来保存学生成绩,使用循环输
入学生成绩。再设计一个循环判断每个学生的成绩是否及格,如果及格则输出,这样就可
以显示所有及格的成绩。同理可以显示所有不及格的成绩。定义两个计数器分别用来记
录及格学生人数和不及格学生人数。

第5 章 显示班级成绩单 67 
5.3.2 参考程序
【程序5.4】 程序StudentInfo.java。 
import java.util. Scanner; 
public class StudentInfo{ 
public static void main(String [] args){ 
final int SIZE = 5; 
double grade[] = new double[SIZE]; 
int pass=0; //定义变量pass 对及格成绩进行计数 
int fail=0; //定义变量fail 对不及格成绩进行计数 
System.out.println("请输入" + SIZE+"个学生的成绩"); 
Scanner sc = new Scanner(System.in); 
for(int i=0; i<SIZE; i++){ 
grade[i] = sc.nextDouble(); 
} 
//统计及格人数,并输出成绩 
System.out.println("及格的学生成绩:"); 
for(int i=0;i<SIZE;i++){ 
if (grade[i]>=60){ 
pass++; 
System.out.println(grade[i]); 
} 
} 
//统计不及格人数,并输出成绩 
System.out.println("不及格的学生成绩:"); 
for(int i=0;i<SIZE;i++){ 
if (grade[i]<60){ 
fail++; 
System.out.println(grade[i]); 
} 
} 
System.out.println("及格的学生有"+pass+"人"); 
System.out.println("不及格的学生有"+fail+"人"); 
} 
} 
程序5.4的编译和运行结果如图5.4所示。
需要对输入的学生成绩进行两遍处理,先使用循环处理所有的成绩,显示及格的学生
成绩;再次循环处理所有成绩,显示不及格学生成绩。为了处理方便,使用数组将学生的
成绩保存起来。程序中先输入5个学生成绩,显示学生成绩的同时统计及格学生人数,不
及格学生人数,最后显示出来。

68 Java 基础与应用(第2 版) 
图5.4 程序5.4运行结果
5.3.3 进阶训练
【程序5.5】 计算圆的面积进阶4。程序4.7中我们实现了多次连续计算圆的面积, 
现在我们使用数组实现一次性的输入多个圆半径,半径保存在数组中,程序将所有圆的面
积计算出来并输出。
程序设计思路分析: 
(1)首先输入圆的个数n; 
(2)定义长度为n的数组r和area,分别存储n个圆的半径和面积; 
(3)利用循环,输入各个圆的半径并存入数组r; 
(4)利用循环,依次从r中取出半径值,并计算圆的面积,计算结果存放在数组area 
中;输出计算结果; 
(5)本题也可以将两个循环合并为一个。
读者按照给出的设计思路,完成程序5.5的编写和编译,运行程序,查看结果是否符
合题目要求。
5.4 拓展知识
5.4.1 数组讨论 
数组访问中经常会遇到的问题是数组下标越界。例如程序5.1中定义的数组double 
grade[]=newdouble[SIZE],这个数组的下标范围是0到SIZE-1,共计SIZE个元素。
常见的错误是访问了下标为SIZE的数组元素,这样程序运行时就会报错,例如程序段: 
int SIZE = 5; 
double grade[] = new double[SIZE]; 
double averageGrade = 0; 
grade[SIZE] = 96;

第5 章 显示班级成绩单 69 
这个程序段运行时会抛出异常,如图5.5所示。
图5.5 数组下标越界异常
这个例子说明两个问题。第一个问题是使用数组时,应该注意代码中是否存在下标
越界。上面例子比较简单,实际应用中,数组下标可能是复杂的表达式或方法的返回值, 
这时候需要小心处理。第二个问题是如果出现数组下标越界的情况应该有相应的异常处
理机制,这样可以保证程序的正确性和有效性。有关异常处理机制参见第17章。
一般对数组进行处理时经常使用for循环,例如程序5.1中的程序段: 
for(int i=0; i<SIZE; i++){ 
averageGrade = averageGrade + grade[i]; 
} 
这是常见的程序段,使用循环变量i来访问数组grade中的每个元素。需要注意一般
在循环体中不要修改循环变量i的值。如果在循环中不小心对变量i的值进行了修改,程
序运行可能会出问题。例如上面程序段修改为: 
for(int i=0; i<SIZE; i++){ 
averageGrade = averageGrade + grade[i]; 
i++; 
} 
在这段程序中,循环变量i的值在循环体中被修改,因此得到的结果会出现错误。这
也是使用循环处理数组经常遇到的问题。
5.4.2 数组的存储
程序中定义的每一个变量,到了程序运行期间都会对应一个内存单元,变量的值保存
在内存单元中,关于变量定义的详细说明见第2章。数组本质上就是一组变量,每个数组
元素都是一个变量。一个数组变量可以存放多个相同类型的数据。例如,程序5.4中定
义的数组变量grade,定义如下: 
int SIZE = 5; 
double grade[] = new double[SIZE]; 
和普通变量类似,这段代码运行时数组变量grade会在内存中对应一段存储区域,里
面包括SIZE(图中的SIZE为5)个存储单元,示意图如图5.6所示。数组grade占用5个
连续的存储空间,每个存储空间分别对应下标为0~4的数组元素。如果想给下标为2的

70 Java 基础与应用(第2 版) 
图5.6 数组内存示意图
数组元素赋一个双精度的数值67.8,则使用语句grade[2]= 
67.8,通过下标实现对数组元素的访问。
图5.6只是一个示意图,用来说明一个数组在内存中的存储
方式。在实际的Java虚拟机中,变量grade是保存在运行栈的数
据区中,而图5.6中数组的存储空间则是在堆区。定义数组的
语句: 
double grade[] = new double[SIZE] 
表示的具体含义是,定义一个double类型数组,数组名字是
grade,变量grade保存在栈上。newdouble[SIZE]表示在堆中开
辟一个存储空间,大小是SIZE个double类型的存储空间。定义
语句中的“=”的作用是让grade指向堆中开辟的空间。相关内容参考第8章中对象和实
例部分的讲解。最后做个简单的总结,本章学习了关键字new,用于创建数组空间,表5-2 
中用粗体表示。其余关键字将在后续章节讲解。
表5-2 Java关键字
abstract extends native return throw 
assert*** finally new static throws 
catch implements package strictfp** transient 
class import private super try 
default instanceof protected synchronized void 
enum**** interface public this volatile 
5.5 实做程序
1.定义一个数组来保存教师工资,编写程序找出并显示最高工资。要点提示,参考
程序5.2的实现。
2.定义一个数组来保存教师工资,编写程序找出并显示最高工资,指出是第几个工
资最高。要点提示: 
(1)参考程序5.2的实现; 
(2)增加一个变量k来记录数值中最高工资对应的下标。
3.定义一个数组来保存教师工资,把最高工资换到数组中的第一个位置,输出交换
后的数组。要点提示: 
(1)找出最高工资和对应下标,例如s[i]; 
(2)与第一个交换,交换是s[0]和s[i],可以使用中间变量temp实现。
4.在实做程序3基础上修改程序,将教师工资按从高到低顺序进行排序。要点
提示: