2.3 流程控制
Java使用了C语言的所有流程控制语句,如分支语句,循环语句、流程跳转语句等。它们用于控制程序的运行流程。
2.3.1 分支语句
分支语句使部分程序代码在满足特定条件下才会被执行。Java语言支持两种分支语句:if … else语句和switch语句。
1.if … else语句
if语句又称为条件语句,其语法格式为:
if(<布尔表达式>) < 语句1>;[else<语句2>;]
其中:<语句1>及<语句2>可以是任何语句,包括复合语句,else部分可以有,也可以没有。
if语句的语义是:首先计算<布尔表达式>的值,若值是true,则执行<语句1>。当<语句1>执行完成,则整个if语句就执行结束了;当<布尔表达式>的值是false时,执行else部分的<语句2>;当<语句2>执行完成,整个if语句就执行结束了。由于if语句中的<语句1>或<语句2>可以是任何语句,则当<语句1>或<语句2> 是另一个if语句时,就产生了if语句的嵌套,例如下面的代码片段:
if (a>1) if (b>10) System.out.println(a+b); else // 此处的else与哪一个if相配? System.out.println(a-b);
这个嵌套的if语句产生了二义性,else与哪一个if相配呢?Java语言规定:else与最近的没有配上else的if相配,故上述的else是与第二个if相配。若要使该else与第一个if相配,则代码如下:
if(a>1){ // 加上一对{},形成一条复合语句 if (b>10) System.out.println(a+b); } else // 此处的else与第一个if相配 System.out.println(a-b);
【例2.4】 设计一个Java程序,判断某一年份是否是闰年。
LeapYear.java
public class LeapYear { public static void main(String[] args){ // args[0]表示命令行的第一个参数并把它由字符串转换为整型 int year = Integer.parseInt(args[0]); int leap; //1表示是闰年,0表示不是闰年 if(year % 4==0){ // 判断能否被4整除 if (year %100 ==0){ if (year %400==0) leap = 1; else leap = 0; } else leap=1; // 是闰年 } else leap = 0; if (leap==1) System.out.println(year +"年是闰年"); else System.out.println(year +"年不是闰年"); } }
右击“LeapYear.java”,选择“Run As”→“Run Configurations”命令,如图2-1所示,选择“Main”标签页,在“Project”栏中选择“MyProject_02”,在“Main class”栏中选择“LeapYear”,选择“Arguments”标签页,在“Program argumentds”栏中输入“1984”,然后单击“Run”按钮,运行程序。
图2-1 计算闰年
程序运行结果:
1984年是闰年
按照上面同样的方式,在“Program argumentds”栏中输入“2009”,然后单击“Run”按钮,运行程序。
程序运行结果:
2009年不是闰年
2.switch语句
当程序有多个分支(通常超过两个)时,使用switch语句比使用多个嵌套的if语句更简明些。switch语句的语法格式如下:
switch(<表达式>) { case <常量表达式1>: [<语句1>] case <常量表达式2>: [<语句2>] … case <常量表达式n>: [<语句n>] [default:<语句n+1>] }
其中:<表达式>的最终值的类型必须是int型或者是能自动转换成int型的类型,如byte、short、char、int,否则,必须进行强制类型转换。<语句1>~<语句n+1>可以是任何语句,也可以缺省不写。<常量表达式1>~<常量表达式n>在编译时就可以计算出它们的值,并将计算出的常量值作为相应语句的一个标号。由于常量值兼作标号,故显然要求不能有两个或以上的常量值相同。
switch语句的语义是:
首先计算<表达式>的值,然后判断该值与<常量表达式1>的值是否相等,若相等,则从<语句1>开始,一直执行到<语句n+1>,即它是一直执行到底的。否则,继续判该值与<常量表达式2>的值是否相等,若相等,则从<语句2>开始,一直执行到底。否则,继续判该值与<常量表达式3>的值是否相等。若没有一个常量表达式的值与<表达式>的值相等,则从default这个标号所代表的语句开始,一直执行到底。
【例2.5】 用switch语句判断当前的季节。
TestSwitch.java
public class TestSwitch { public static void main(String[] args) { int x= 0; //args[0]表示命令行的第一个参数并把它由字符串转换为整型 x = Integer.parseInt(args[0]); switch (x) { case 1: System.out.println("It is spring now!");break; case 2: System.out.println("It is summer now!");break; case 3: System.out.println("It is autumn now!");break; default: System.out.println("It is winter now!"); } } }
右击“TestSwitch.java”,选择“Run As”→“Run Configurations”命令,如图2-2所示,选择“Main”标签页,在“Project”栏中选择“MyProject_02”,在“Main class”栏中选择“TestSwitch”。
图2-2 判断当前的季节
选择“Arguments”标签页,在“Program argumentds”栏中输入“1”,然后单击“Run”按钮,运行程序。
程序运行结果:
It is spring now!
2.3.2 循环语句
循环语句的作用是反复执行一段代码,直到不满足循环条件为止。循环语句一般应包括如下4部分内容:
(1)初始化部分:用来设置循环的一些初始条件,比如设置循环控制变量的初始值。
(2)循环条件:这是一个布尔表达式,每一次循环都要对该表达式求值,以判断是否继续循环。
(3)循环体:这是循环操作的主体内容,可以是一条语句,也可以是多条语句。
(4)迭代部分:通常属于循环体的一部分,用来改变循环控制变量的值,从而改变循环条件表达式的布尔值。
Java语言有3种循环语句:for语句、while语句和do … while语句。for和while语句在执行在执行循环体之前测试循环条件,而do … while语句在执行完循环体之后测试循环条件。这意味着for和while语句可能连一次循环体都未执行,而do … while循环至少执行一次循环体。
1.while语句
while语句的语法格式是:
while(<布尔表达式>) { <语句1> <语句2> … <语句n> }
其中:<布尔表达式>是循环继续下去的条件,循环体中的<语句1>~<语句n>可以是任意合法的Java语句。若循环体中只有一条语句,则循环体的一对花特号{}可以省略不写。
while语句的语义是:
第1步:计算<布尔表达式>的值,若值是false,则整个while语句执行结束,程序将继续执行紧跟在该while循环体之后的语句,而循环体中的语句,一次都没有得到执行。若值是true,则转第2步。
第2步:依次执行循环体中的<语句1>、…、<语句n>,再转第1步。
注意:循环体或布尔表达式中至少应该有这样的操作,它的执行会改变或影响while(<布尔表达式>)中<布尔表达式>的值,否则while语句就会永远执行下去,不能终止,成为一个死循环。例如:
int a = 1, b = 2; while( a<b) { b++; a += 2; }
2. do … while语句
do…while语句的语法格式是:
do { <语句1> <语句2> … <语句n> } while(<布尔表达式>);
其中:<布尔表达式>是循环继续下去的条件,循环体中的<语句1>、…、<语句n>可以是任何合法的Java语句。
注意:即使循环体中只有一条语句,循环体的一对花括号({})也不能省略不写。
do … while语句的语义是:
第1步:依次执行循环体中的<语句1>、…、<语句n>。
第2步:计算<布尔表达式>的值,若值是false,则整个do … while语句执行结束,程序继续执行紧跟在该do … while语句之后的语句。若值是true,则转第1步。
从do … while语句的语义中可知,循环体中的语句至少执行一次,即循环体最少执行的次数是1次。同while语句一样,循环体或布尔表达式中至少应该有这样的操作,它的执行会改变或影响while(<布尔表达式>)中<布尔表达式>的值,否则,do … while语句就会永远执行下去,不能终止,成为一个死循环。
【例2.6】 设计一个Java程序,打印出1*2*3*…*n之积,变量n的初始值在程序中指定。
MultiplyCalculate.java
public class MultiplyCalculate { public static void main(String[]args){ long s =1; int k=Integer.parseInt(args[0]); // 把字符串转换为整型 for (int i = 1;i <k;i++){ s = s * i ; } System.out.println("1*2*3"+"…*"+k+"="+s); // 打印相乘的结果 } }
右击“MultiplyCalculate.java”,选择“Run As”→“Run Configurations”命令,如图2-3所示,选择“Main”标签页,在“Project”栏中选择“MyProject_02”,在“Main class”栏中选择“MultiplyCalculate”,选择“Arguments”标签页,在“Program argumentds”栏中输入“10”,然后单击“Run”按钮,运行程序。
图2-3 计算整数相乘的结果
程序运行结果:
1*2*3*… *10=3628800
3.for语句
for语句与while语句一样,也是先判断循环条件,再执行循环体。它的语法格式是:
for (e1;e2;e3) { <语句1> <语句2> … <语句n> }
其中:e1是用逗号分隔的Java中任意表达式的列表。e1可以默认不写,但e1后的分号不能省略;e2是布尔表达式,表示循环继续执行的条件,若该部分默认,则表示条件永远为真,成为死循环,但e2后的分号同样不能省略;e3同样是用逗号分隔的Java中任意表达式的列表,也可以缺省不写。循环体中的<语句1>、…、<语句n>可以是任何合法的Java语句。若循环体中只有一条语句,则循环体的一对花括号可以省略不写。
for语句的语义是:
第1 步:首先从左到右依次执行e1 中用逗号分隔的各个表达式,这些表达式仅在此执行一次,以后不再执行,通常用于变量初始化赋值。
第2 步:计算布尔表达式e2 的值。若值为false,则整个for循环语句执行结束,程序继续执行紧跟在该for语句之后的语句;若值为true,则依次执行循环体中<语句1>、…、<语句n>。
第3步:从左到右依次执行e3中用逗号分隔的各个表达式,再转第2步。
【例2.7】 设计一个Java程序,输出所有的水仙花数。所谓水仙花数,是一个3 位数,其各位数字的立方和等于该数自身,例如,153 = 13+53+33。
TestNum.java
public class TestNum { public static void main(String[] args){ int i=0; // 百位数 int j=0; // 十位数 int k=0; // 个位数 int n = 0; int p = 0; for( int m = 100; m <1000; m++){ i=m/100; // 得到百位数 n = m %100; j=n/10; // 得到十位数 k=n %10; // 得到个位数 p = i*i*i+j*j*j+k*k*k; if (p==m){ System.out.println(m); // 打印水仙花数 } } } }
程序运行结果:
153 370 371 407
2.3.3 流程跳转语句
break、continue和return语句用来控制流程的跳转。
(1)break:从switch语句、循环语句或标号标识的代码块中退出。以下while循环语句用于计算从1加到100的值。
int a = 1,result = 0; while (true) { result += a++; if (a == 101) break; } System.out.println(result);
(2)continue:跳过本次循环,立即开始新的一轮循环。
【例2.8】 打印100~200之间能被3整除的数,每10个数一行。
TestContinue.java
public class TestContinue { public static void main(String[] args) { int n = 0; int i = 0; for (n = 100; n <= 200; n++) { if (n % 3 != 0) continue; // 不能被3整除,结束本次循环 i++; System.out.print(n+" "); if(i % 10==0){ // 每10个数一行 System.out.println(); } } } }
程序运行结果:
102 105 108 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162 165 168 171 174 177 180 183 186 189 192 195 198
(3)return:退出本方法,跳到上层调用方法。如果本方法的返回类型不是void,则需要提供相应的返回值。