
3.3 控制语句
计算机语言通过控制语句执行程序流,从而完成一定的任务。程序流由若干个语句组成,语句可以是单一的一条语句,如z=x+y,也可以是用大括号“{}”括起来的一个复合语句。
计算机语言有3种控制流程:顺序、分支和循环。
(1)顺序(Sequence):应用程序一行一行地顺序执行。
(2)分支(Branch):根据表达式结果或变量状态使程序选择不同的执行路径。
(3)循环(Loop):使程序能够重复执行一个或一个以上语句。也就是说,重复语句形成循环。
Java的控制语句包括以下语句。
(1)分支语句:if…else、switch。
(2)循环语句:while、do…while、for。
(3)与程序转移有关的其他语句:break、continue、return。
(4)异常处理语句:try…catch…finally、throw。
其中的异常处理语句将专门在后面的章节讨论。
3.3.1 顺序流程
顺序结构是程序设计中最简单的一种程序结构,其特点是完全按照语句出现的先后次序执行程序。在日常生活中,需要“按部就班、依次进行”处理和操作的问题随处可见。顺序流程是最简单的,应用程序默认的就是一行一行地顺序执行。这里不再赘述。
在顺序结构中,程序的流程是固定的,不能跳转,只能按照书写的先后顺序、逐条逐句地执行。这样,一旦发生特殊情况,无法进行特殊处理。但实际问题中,有很多时候需要根据不同的判定条件执行不同的操作步骤,这就需要采用选择流程来处理。
3.3.2 选择流程
在程序设计过程中,经常先给出问题中需要用来进行判断的条件,然后再根据实际运行情况对给定的条件进行判断,依据条件成立与否来选择执行不同的操作,这种结构的程序设计流程称为选择流程。选择结构流程图如图3-3所示。

图3-3 选择结构流程图
从上面的流程图中可以看出,在选择结构程序设计中首先要做的是设计用来判断的条件(条件表达式)。在前面的章节已经学习了关系和逻辑运算符的使用,在Java程序中通常需要用关系和逻辑运算符来构成条件判断表达式。下面来看一个例子。
【例3-13】 编写程序,判断学生成绩是否合格。
算法分析与设计:在本例中,学生成绩用变量score表示,因此判断学生成绩是否合格,实际上就是判断学生成绩是否大于或等于整数60。如果学生成绩(score)大于或等于整数60,则该学生成绩为合格,否则为不合格,其流程图如图3-4所示。

图3-4 判断学生成绩是否合格流程图
程序如下:

当用户在运行程序时,将得到如下两种不同的运行结果。
(1)当分数高于60分时,例如75分,则输出:

(2)当分数低于60分时,例如58分,则输出:

在上面的例子中,if…else…是典型的选择结构程序语句,表示“如果……否则……”。
通过上面的例题可以看出,选择结构程序设计就是根据给定的条件执行相应的操作语句的程序设计。
选择结构程序设计中最常用的一种语句是if语句,因此通常也把if语句称为条件分支语句。Java语言提供了两种形式的if语句:if…else形式(标准双分支选择)、if…else…if或if…if…else等形式(嵌套选择形式)。
1. 选择结构的标准语句形式if…else
if…else形式又称为双分支选择,是if语句中最常使用的标准形式。其语法格式如下:


图3-5 if…else形式的程序流程图
语句含义为:判断括号内表达式的值,若为非0,执行语句1;否则,执行语句2。if…else形式的程序流程图如图3-5所示。
注意:①布尔表达式是任意一个返回布尔数据类型的表达式,而且必须是布尔数据类型;②每个单一语句后面都要有分号;③为了增强程序的可读性,应将if或else后的语句用{}括起来。
【例3-14】 设计一个应用程序,判断某一年是否为闰年。
算法设计:通常判断某年为闰年有如下两种情况。
(1)该年的年号能被4整除但不能被100整除。
(2)该年的年号能被400整除。
假设在程序中用整型变量Y表示该年的年号。
上述两种情况可以分别表示如下。
第一种情况为:(Y%4==0)&&(Y%100!=0)。
第二种情况为:Y%400==0。
在上述两种情况中,只要能让其中任何一种成立,即可断定该年为闰年,因此最终用来判断某年是否为闰年的表达式为
(Y%4==0)&&(Y%100!=0)||(Y%400==0)
当表达式的值为1时,则该年为闰年;当表达式的值为0时,则为非闰年。
程序如下:

程序运行结果:

注意:在条件语句中的“等于”用双等号“==”,要区别于赋值语句中的“赋值”用的单一等号“=”。||为“或”(或者),&&为“与”(并且)。
2. 选择结构的嵌套if语句形式
嵌套在程序设计中是一种非常常见的结构,在某一个结构中的某一条执行语句本身又具有相同的结构时就称为嵌套。一个if语句又包含一个或多个if语句(或者说if语句中的执行语句本身又是if结构语句)称为if语句的嵌套。当流程进入某个选择分支后又引出新的选择时就要用嵌套if语句。
嵌套if语句的标准语法格式为

嵌套if语句的含义为:首先判断表达式1的值,若表达式1为非0,再判断表达式2的值,若表达式2为非0,则执行语句1,否则执行语句2。若表达式1的值为0,再判断表达式3的值,若表达式3为非0,则执行语句3,否则执行语句4。嵌套if语句的流程图如图3-6所示。
这种在if语句中本身又包含if语句的选择结构,常用于解决比较复杂的选择问题,其中的每一条语句都必须经过多个条件共同决定才能执行(如同行人要到某个目的地,只有在每个十字路口都做出正确选择后才能达到一样)。

图3-6 嵌套if语句的流程图
有关嵌套if语句使用的几点说明如下:
(1)嵌套if语句的使用非常灵活,不仅标准形式的if语句可以嵌套,其他形式的if语句也可以嵌套;被嵌套的if语句可以是标准形式的if语句,也可以是其他形式的if语句。例如:

(2)被嵌套的if语句本身又可以是一个嵌套的if语句,称为if语句的多重嵌套。
(3)在多重嵌套的if语句中,else总是与离它最近并且没有与其他else配对的if是配对关系。
注意:按上面所述的if与else配对的关系,应该能够分清楚if与else之间的匹配关系。嵌套if语句的书写风格,应该把处于同一逻辑意义上的语句写在同一列上,使程序从形式上更清晰、更美观。这种缩进格式只是略微增加了源程序的长度,编译后目标程序丝毫不会受影响,因此大可不必担心采用缩进格式后程序会变得臃肿。
【例3-15】 给定一个百分制成绩,要求根据分数输出成绩等级:'A'、'B'、'C'、'D'、'E'。90分及90分以上为'A',80~89分为'B',70~79分为'C',60~69分为'D',60分以下为'E'。
算法设计:在此问题中只需定义一个实型变量用来存放学生成绩即可,其他如'A'、'B'、'C'等均可以在输出函数中用普通字符表示。本题选择多分支if结构即可解决。
程序如下:

程序运行结果:

提示:在if…else…if形式的if语句中,后一个表达式的执行是在前面表达式不成立的基础上进行的,因此后面条件的描述中实际上已经包含对前面条件的否定,如上例中else if(score<70)中的score<70相当于score>=60&&score<70。
有关if语句使用的几点说明如下:
(1)if语句中的条件表达式必须用()括起来,并且在括号外部不能加分号。
(2)if或else子句后面的执行语句均有分号。
(3)else是if语句的子句,必须与if搭配使用,不可以单独使用。
(4)当if或else子句后是多个执行语句构成的语句组时(复合语句),必须用{}括起来,否则各子句均只管到其后第一个分号处。例如:

(5)if或else子句后只接单个分号时,应将其作为空语句处理。
(6)可以用条件表达式简化if语句。例如:

这段代码也可以简写成下面的形式:
y=a>b?a:b;
即可以用条件表达式书写,这样的写法在Java语言中经常用到,好处在于代码简洁,并且有一个返回值。
3. switch语句
switch语句又称开关语句,在Java程序中专门用来处理多分支选择问题。用switch语句编写的多分支选择程序就像一个多路开关,使程序流程形成多个分支,使用起来比复合if语句及嵌套if语句更加方便灵活。
【例3-16】 用switch语句实现学生成绩的等级评定。
给定一个百分制成绩,要求根据分数输出成绩等级:'A'、'B'、'C'、'D'、'E'。90分及90分以上为'A',80~89分为'B',70~79分为'C',60~69分为'D',60分以下为'E'。
程序如下:

程序运行结果:

switch语句的语法格式如下:

switch语句的含义为:先计算表达式的值,判断此值是否与某个常量表达式的值匹配,如果匹配,控制流程转向其后相应的语句;否则,检查default是否存在,如存在则执行其后相应的语句,否则结束switch语句。switch语句的流程图如图3-7所示。

图3-7 switch语句的流程图
使用switch语句设计多分支选择结构程序,不仅使用更加方便,而且程序可读性也更高。
有关switch语句使用的几点说明如下:
(1)括号内的表达式的返回值类型必须是int、byte、char、short、String类型和枚举类型之一。
(2)case子句中的值必须是常量,case后的每个常量表达式必须各不相同。
(3)default子句是任选的,并且可以放在任何位置。
(4)每个case之后的执行语句可多于一个,但不必加{}。
(5)switch语句不像if语句那样只要满足某一条件则可在执行相应的分支后自动结束选择。break语句用来在执行完一个case分支后,使程序跳出switch语句,即终止switch语句的执行。如果某个case分支后没有break语句,程序将不再做比较而继续执行后面所有case分支的语句,因此需要在每个case分支的最后加上一条break语句以帮助结束选择。
(6)switch、break、default均为Java语言的关键字。switch语句的功能可以用if…else语句来实现,但某些情况下,使用switch语句更为简练。
相关知识 break语句。
break语句在Java语言中称为中断语句,只有关键字break,没有参数。break语句不仅可以用来结束switch的分支语句,也可以在循环结构中实现中途退出,即在循环条件没有终止前也可以使用break语句来跳出循环结构。
注意:在JDK12中重新增强了switch,它引入了一种新形式的标签,写成case L->,用来表示如果标签匹配,则只执行标签右侧的代码,通过扩展现有的switch语句,可将其作为增强版的switch语句或者是“switch表达式”来简化代码。
【例3-17】 增强switch使用实例。

编译运行结果如下:

3.3.3 循环控制流程
循环结构是程序设计中一种非常重要的结构,几乎所有的实用程序中都包含循环结构,应该牢固掌握。
Java语言可以组成各种不同形式的循环结构,分别由while语句、do…while语句和for语句来实现、增强型for…each循环。为了更方便地控制程序流程,Java语言还提供了循环辅助控制语句:break、continue和return语句。
1. while语句实现循环(当型循环)
【例3-18】 利用while语句求sum=1+2+3+…+10。
算法流程参见图3-8。

图3-8 例3-18循环N-S图
程序如下:

程序运行结果:

上面的例子中,i表示循环变量,sum存放累加和。“i=1,sum=0”,表示进入循环前需要设置“初值”,该语句只执行一次;i<=10表示循环执行的“条件”:当变量i的值超过10时,循环结束,否则反复执行“循环体语句”:sum=sum+i;i=i+1。
上述循环程序运行过程分析如下:

相关知识 While语句。
while语句的一般形式如下:

或

其中,表达式称为“循环条件”,语句称为“循环体”。为便于初学者理解,可以读作“当条件(循环条件)成立(为真),循环执行语句(循环体)”。
执行过程如下:
(1)先计算while后面的表达式的值,如果其值为“真”,则执行循环体。

图3-9 while语句实现循环的流程图
(2)执行一次循环体后,再判断while后面的表达式的值,如果其值为“真”,则继续执行循环体,如此反复,直到表达式的值为假,退出此循环结构。
while语句实现循环的流程图如图3-9所示。
使用while语句需要注意以下几点:
(1)while语句的特点是先计算表达式的值,然后根据表达式的值决定是否执行循环体中的语句。因此,如果表达式的值开始就为“假”,那么循环体一次也不执行。
(2)当循环体由多个语句(两个以上的语句)组成时,必须用{}括起来,形成复合语句。
(3)在循环体中应有使循环趋于结束的语句,以避免“死循环”的发生。
思考:

图3-10 例3-19程序N-S图
(1)在例题3-18的基础上如何求sum=1+1/2+1/4+…+1/50?
(2)如何求s=1×2×3×…×10,即求10!。
2. do…while语句实现循环(直到型循环)
【例3-19】 利用do…while语句求sum=1+2+3+…+10。
do…while循环的执行流程如图3-10所示。
程序如下:

程序运行结果:

do…while语句的一般形式:
do { 语句序列; }while(表达式);
说明:表达式称为“循环条件”,语句称为“循环体”。为便于初学者理解,可以读作:“执行语句(循环体),当条件(循环条件)成立(为真)时,继续循环”,或者“执行语句(循环体),直到条件(循环条件)不成立(为假)时,循环结束”。do…while语句实现循环的流程图如图3-11所示。

图3-11 do…while语句实现循环的流程图
do…while语句执行过程如下:
(1)执行do后面的循环体语句。
(2)计算while后面的表达式的值,如果其值为“真”,则继续执行循环体,直到表达式的值为假,退出此循环结构。
注意:do…while循环与while循环的以下区别。
(1)do…while循环,总是先执行一次循环体,然后再求表达式的值。因此,无论表达式是否为“真”,循环体至少执行一次。
(2)while循环先判断循环条件再执行循环体,循环体可能一次也不执行。

图3-12 例3-20程序N-S图
(3)在if语句、while语句中,表达式后面都不能加分号,而在do…while语句的表达式后面则必须加分号。
3. for语句实现循环
【例3-20】 利用for语句求sum=1+2+3+…+10。
算法流程参见图3-12。
程序如下:

程序运行结果:

例3-20中,i=1表示循环变量i的初值为1,该语句只执行一次;i<=10表示循环执行的条件,当变量i的值超过10时,循环结束,否则反复执行循环体语句sum=sum+i;和本程序中使循环趋于结束的语句i=i+1;。在进入循环之前将存放累加和的变量sum初值置0。执行结果与例3-19结果是一样的。
for语句的一般形式如下:

等价于


图3-13 for语句实现循环的流程图
说明:for是关键字,其后有3个表达式,各个表达式用分号分隔。3个表达式可以是任意的表达式,主要用于for循环控制。for语句实现循环的流程图如图3-13所示。
for循环执行过程如下:
(1)先计算表达式1。
(2)然后计算表达式2,若其值为非0(循环条件成立),则转(3)执行循环体;若其值为0(循环条件不成立),则转(5)结束循环。
(3)执行循环体。
(4)计算表达式3,然后转(2)。
(5)结束循环,执行for循环之后的语句。
说明:for语句中有3个表达式,以分号分隔。表达式1可以是设置循环变量初值的表达式(常用),也可以是与循环变量无关的其他表达式;表达式2一般为关系表达式或逻辑表达式,也可以是数值表达式或字符表达式,事实上只要是表达式就可以。
for语句的使用非常灵活,注意区别下列程序段完成的功能,体会for语句的灵活性。
(1)表达式1为逗号表达式,上述例题中的循环语句可以写为

在实际应用中,表达式3也可以是逗号表达式,例如上例中的循环语句可以写为此时省略了循环体。

(2)循环控制变量初值大于终值,步长为-1(步长递减),上述例题中的循环语句可以写为

(3)省略表达式1,上述例题中的循环语句可以写为

(4)省略表达式3,上述例题中的循环语句可以写为

(5)若表达式2省略,for(;;)语句相当于while(1)。若退出循环,需要后面介绍的终止循环的语句。
4. 多重循环(嵌套循环)
一个循环体内又包含另一个完整的循环结构即为循环套循环,这种结构称为多重循环(嵌套循环)。
按照循环的嵌套次数,分别称为二重循环、三重循环。一般将处于内部的循环称为内循环,处于外部的循环称为外循环。一般单重循环只有一个循环变量,双重循环具有两个循环变量,多重循环有多个循环变量。
【例3-21】 打印九九乘法表。


图3-14 例3-21程序N-S图
算法分析:观察上面的乘法表可以看出:
第一行为1×i=i;第二行为2×i=2i;第三行为3×i=3i……第九行为9×i=9i。
行号i从1到9,每次递增1,其算法流程如图3-14所示,可以用下面的程序实现。

程序运行结果:

说明:
- 一个循环体必须完完整整地嵌套在另一个循环体内,不能出现交叉现象。
- 多层循环的执行顺序:最内层先执行,由内向外逐层展开。
- 3种循环语句构成的循环可以互相嵌套。
- 并列循环允许使用相同的循环变量,但嵌套循环不允许。
相关知识 增强型for循环。
JDK的版本在不断升级后,增加了很多新的特性,在JDK 5.0以后的版本中增强了for循环,目的是简化针对数组及集合类型的访问,特点是简单。例如,在没有增强型for循环时如下这样操作数组:

在使用了新的增强型for循环后,代码得到了简化:

增强型for循环语句是从数组或者集合中连续一一取出其中保存的元素,这样简化了Java程序员遍历数组或者集合的操作。有关数组以及集合类型的内容,后面章节将详述。
5. 与程序转移有关的其他语句
1)break语句
在switch语中,break语句用来终止switch语句的执行,使程序从整个switch语句后的第一条语句开始执行。
在Java中,可以为每个代码块加一个标号,一个代码块通常是用大括号括起来的一段代码。加标号的格式如下:
break[标号];
break语句就是让程序跳出它所指定的块,并从紧跟该块后的第一条语句处执行。
【例3-22】 break语句的应用:打印1~10的所有奇数。
程序如下:

程序运行结果:

注意:因为标号会带来程序混乱,应该尽量避免使用标号。
2)continue语句
continue语句用来结束本次循环,跳过循环体中下面尚未执行的语句,接着进行终止条件的判断,以决定是否继续循环。对于for语句,在进行终止条件的判断前还要先执行迭代语句。continue语句的格式如下:

也可以用continue跳转到括号指明的外层循环中,这时的格式为

【例3-23】 continue的应用:打印1~10的所有奇数。
程序如下:

程序运行结果:

说明:上面的例子,当i是偶数时就跳过本次循环后的代码,直接执行for语句中的第三部分,然后进入下一次循环的比较,是奇数就打印i。