流程控制语句是用来控制程序中各语句执行顺序的语句,是程序中非常关键和基本的部分。流程控制语句可以把单个的语句组合成有意义的,能完成一定功能的小逻辑模块,能否熟练地运用流程控制语句往往很大程度上影响所编写程序的质量。最主要的流程控制方式是结构化程序设计中规定的三种基本流程结构。
结构化程序设计
结构化程序设计原则是公认的面向过程编程应遵循的原则,它使得程序段的逻辑结构清晰、层次分明,有效地改善了局部程序段的可读性和可靠性,保证了其质量,提高了开发效率。
结构化程序设计的最基本的原则是:任何程序都可以且只能由3种基本流程结构构成,即顺序结构、分支结构和循环结构。
顺序结构是3种结构中最简单的一种,即语句按照书写的顺序依次执行;分支结构又称为选择结构,它将根据计算所得的表达式的值来判断应选择执行哪一个流程的分支;循环结构则是在一定条件下反复执行一段语句的流程结构。这3种结构构成了程序局部模块的基本框架。
Java语言虽然是面向对象的语言,但是在局部的语句块内部,仍然需要借助于结构化程序设计的基本流程结构来组织语句,完成相应的逻辑功能。Java的语句块是由一对大括号括起的若干语句的集合。Java中有专门负责实现分支结构的条件分支语句和负责实现循环结构的循环语句。
Java中的分支语句有两个,一个是负责实现双分支的if语句,另一个是负责实现多分支的开关语句switch。
1. if 语句
if语句的一般形式是:
if(条件表达式P)
语句1; // if分支
else
语句2; // else分支
其执行过程可表示为下所示:

其中条件表达式用来选择判断程序的流程走向,在程序的实际执行过程中,如果条件表达式的取值为真,则执行if分支的语句块,否则执行else分支的语句块。在编写程序时,也可以不书写else分支,此时若条件表达式的取值为假,则绕过if分支直接执行if语句后面的其他语句。
求x、y中的最大数。
public class maxNumber{
public static void main(String args[]){
int x,y; //x、y、max为局部变量
int max;x=135;y=348;
if(x>y)
max=x;
else
max=y;
System.out.println("max="+max);
}
}
2. switch语句
switch语句是多分支的开关语句,它的一般格式如下:
switch (表达式){
case 值1: 语句块1 //分支1
case 值2: 语句块2 //分支2
……
case 值n: 语句块n //分支n
default:语句块n+1 //分支n+1
}
switch语句在执行时,首先计算表达式的值,这个值必须是整型或字符型,同时应与各个case分支的判断值的类型相一致。计算出表达式的值之后,将它先与第一个case分支的判断值相比较,若相同,则程序的流程转入第一个case分支的语句块;否则,再将表达式的值与第二个case分支相比较……依此类推。如果表达式的值与任何一个case分支都不相同,则转而执行最后的default分支;在default分支不存在的情况下,则跳出整个switch语句。
需要注意的是,switch语句的每一个case判断,都只负责指明流程分支的入口点,而不负责指定分支的出口点,分支的出口点需要编程人员用相应的跳转语句来标明,如果希望程序的逻辑结构正常完成分支的选择,则需要为每一个分支另外编写退出语句。
break是流程跳转语句。通过引入break语句,定义了各分支的出口,多分支开关语句的结构就完整了。在某些情况下,switch语句的这个只有分支入口、没有出口的功能也有它独特的适用场合。如在若干判断值共享同一个分支时,就可以实现由不同的判断语句流入相同的分支。
用switch语句判断一个月份属于一年中的哪个季节(春、夏、秋、冬)。
import java.util.*;
public class SwitchDemo{
public static void main(String args[]){
Scanner in=new Scanner(System.in);
int month=in.nextInt();//从键盘读月份
String season=””;
switch(month){
case 12: //此处没有使用break
case 1:
case 2:
season="冬季";
break;
case 3:
case 4:
case 5:
season="春季";
break;
case 6:
case 7:
case 8:
season="夏季";
break;
case 9: //值为10和9时的操作是相同的
case 10:
case 11:
season="秋季";
break;
default:
season="错!";
break;
}
System.out.println(month+"月份属于:"+season);
}
}
运行这个程序会得到如下输出结果:
7月份属于:夏季
循环结构是在一定条件下反复执行某段程序的流程结构,被反复执行的程序被称为循环体。循环结构是程序中非常重要和基本的一种结构,它是由循环语句来实现的。Java的循环语句共有3种:while语句、do-while语句和for语句。
1. while语句
while语句的一般语法格式如下:
while(条件表达式)循环体
其执行过程可表示为下图所示:

其中条件表达式的返回值为布尔型,循环体可以是单个语句,也可以是复合语句块。
while语句的执行过程是先判断条件表达式的值,若为真则执行循环体,循环体执行完之后再无条件转向条件表达式再做计算与判断;当计算出条件表达式为假时,跳过循环体执行while语句后面的语句。下面是一个使用while语句的任务:
找出所有的水仙花数并输出。
public class Narcissus{
public static void main(String args[]){
int i,j,k,n=100,m=1;
while(n<1000){
i = n/100;j = (n-i*100)/10;k = n%10;
if((Math.pow(i,3) + Math.pow(j,3) + Math.pow(k,3)) == n)
System.out.println("找到第"+ m++ + "个水仙花数:" + n);
n++;
}
}
}
其功能是找出所有的水仙花数并输出。水仙花数是三位数,它的各位数字的立方和等于这个三位数本身,例如371=33+73+13,则371就是一个水仙花数。程序中定义了一个while循环,每轮循环检查100~999中的一个三位数n,取出n的个位、十位和百位数分别存入k、j、i三个整型变量;利用系统定义好的方法Math.pow()计算i、j、k的三次方并相加,若所得的和等于n,则输出这个水仙花数;否则n加1检查下一个三位数。循环结束时所有的三位数都将被检查到。运行结果如图所示。

2. do-while语句
do-while语句的一般语法结构如下:
do
循环体
while(条件表达式);
其执行过程可表示为下图所示:

do-while语句的使用与while语句很类似,不同的是它不像while语句是先计算条件表达式的值,而是无条件地先执行一遍循环体,再来判断条件表达式。若表达式的值为真,则再运行循环体,否则跳出do-while循环,执行下面的语句。可以看出,do-while语句的特点是它的循环体将至少被执行一次。下面是使用do-while语句的任务。
import java.io.*;
public class showCharValue{
public static void main(String args[]){
char ch;
try{
System.out.println("请输入一个字符,以'#'结束");
do{
ch=(char)System.in.read();
System.out.println("字符"+ch+"的整数值为"+(int)ch);
System.in.skip(2);//跳过回车键
}while(ch!='#');
}catch(IOException e){System.err.println(e.toString());}
}
}
运行结果如图所示。

3 . for语句
for语句是Java语言三个循环语句中功能较强、使用较广泛的一个。for语句的一般语法格式如下:
for(表达式1;表达式2;表达式3)循环体
其中表达式2是返回布尔值的条件表达式,用来判断循环是否继续;表达式1完成初始化循环变量和其他变量的工作;表达式3用来修整循环变量,改变循环条件,三个表达式之间用分号隔开。
for语句的执行过程是这样的:首先计算表达式1,完成必要的初始化工作;再判断表达式2的值,若为真,则执行循环体,执行完循环体后再返回表达式3,计算并修改循环条件,这样一轮循环就结束了。第二轮循环从计算并判断表达式2开始,若表达式的值仍为真,则继续循环,否则跳出整个for语句执行下面的句子。for语句的三个表达式都可以为空,但若表达式2也为空,则表示当前循环是一个无限循环,需要在循环体中书写另外的跳转语句终止循环。
其执行过程可表示为下图所示:

找出10000之内的所有完全数。
public class PerFectNum{
public static void main(String args[]){
int count=1;
for(int i=1;i<10000;i++){
int y=0;
for(int j=1;j<i;j++)
if(i%j==0)y+=j;
if(y==i){
System.out.print(i+String.valueOf('\t'));count++;
if(count%3==0)System.out.println();
}
}}}
其功能是输出10000之内的所有完全数。完全数是指等于其所有因子和(包括1但不包括这个数本身)的数。例如6=1×2×3,6=1+2+3,则6是一个完全数。for循环检查1到9 999之间的所有整数是否是完全数。每轮循环检查一个数i是否是完全数。嵌套在大循环中的小循环,用来求出数i的因子和。如果i等于这个因子和,则i为完全数则输出它。变量count用来计算所求得的完全数个数。最后使得每输出两个完全数后加入一个换行。运行结果如图:

跳转语句用来实现程序执行过程中流程的转移。前面在switch语句中使用过的break语句就是一种跳转语句。为了提高程序的可靠性和可读性,Java语言不支持无条件跳转的goto语句。Java的跳转语句有3个:continue语句、break语句和return语句。1. continue语句
continue语句必须用于循环结构中,它有两种使用形式:
一种是不代标号的continue语句,它的作用是终止当前这一轮的循环,跳过本轮剩余的语句,直接进入当前循环的下一轮。在while或do-while循环中,不带标号的continue语句会使流程直接跳转至条件表达式。在for循环中,不带标号的continue语句会跳转至表达式3,计算修改循环变量后再判断循环条件。
另一种是带标号的continue语句,其格式是:
continue 标号名;
这个标号名应该定义在程序中外层循环语句的前面,用来标志这个循环结构。标号的命名应该符合Java标识符的规定。带标号的continue语句使程序的流程直接转入标号标明的循环层次。
下面查找1~100之间的素数的代码中使用了带标号的continue语句。如果找到整数i的一个因子j,则说明这个i不是素数。程序将跳过本轮循环剩余的语句直接进入下一轮循环,检查下一个数是否是素数。
First-Loop:
for(int i=1;i<100;i++){
for(int j=2;j<i;j++)
if(i%j==0)continue First-Loop;
System.out.println(i);
}
2. break语句
break语句的作用是使程序的流程从一个语句块内部跳转出来,如从switch语句的分支中跳出,或从循环体内部跳出。break语句同样分为带标号和不带标号两种形式。带标号的break语句的使用格式是:
break 标号名;
这个标号应该标志某一个语句块。执行break语句就从这个语句块中跳出来,流程进入该语句块后面的语句。
不带标号的break语句从它所在的switch分支或最内层的循环体中跳转出来,执行分支或循环体后面的语句。
3. return语句
return语句的一般格式是:
return 表达式;
return语句用来使程序流程从方法调用中返回,表达式的值就是调用方法的返回值。如果方法没有返回值,则return语句中的表达式可以省略。