Java语言提供3种基本的流程控制结构——顺序结构、分支结构和循环结构。其中结构用于实现根据条件来选择性地执行某段代码,循环结构则用于根据循环条件重复执行某段代码。
一、顺序结构
任何编程语言中最常见的程序结构就是循序结构,顺序结构就是程序从上到下一行一行的执行,中间没有任何判断和跳转。
如果main方法多行代码之间没有任何流程控制,则程序总是从上向下依次执行,排在前面的代码先执行,排在后面的代码后执行。这意味着:如果没有流程控制,java方法里的语句是一个顺序执行流,从上向下依次执行每条语句。根据语句出现的先后顺序依次执行。
二、分支结构
根据条件从两个分支或多个分支中选择其一执行。Java提供了两种常见的分支控制结构:if语句和switch语句。其中,if语句使用布尔表达式或布尔值作为分支条件来进行分支控制;而switch语句则用于对多个整型值进行匹配,从而实现分支控制。
1.if条件语句
If语句使用布尔表达式或布尔值作为分支条件进行分支控制,有以下三种形式
第一种形式:
<pre name="code" class="java">if (logic expression ){
statements…
}
第二种形式:
if (logic expression){
statements…
}
else{
statements…
}
第三种形式:
if (logic expression){
statements…
}
else if(logic expression)
{
statements…
}
…//可以有零个或多个else if语句
else{
//最后的else语句也可以省略
Statement…
}
在上面if语言的三种形式中,放在if之后的括号里的只能是一个逻辑表达式,即这个表达式的返回值只能是true或false.第二种情形和第三种情形是相通的,如果第三种形式中else if块不出现,则变成了第二种形式。
上面的条件语句中,if(logic expression)、else if(logic expression)以及else后花括号括起来多行代码被称为代码块,一个代码块通常被当成一个整体来执行(除非运行过程中遇到return、break、continue等关键字,或者遇到了异常),因此这个代码块也被称为条件执行体。
例如如下程序:
程序清单:TestIf.java
public class TestIf{
public static void main(String[] args){
int age = 30;
if (age > 20){
//只有当age > 20时,下面花括号括起来的语句块才会执行
//花括号括起来的语句是一个整体,要么一起执行,要么一起不会执行
System.out.println("年龄已经大于20岁了");
System.out.println("20岁以上的人应该学会承担责任…");
}
}
}
因此,如果if(logic expression)、else if(logic expression)和else后的语句块只有一行语句时,则可以省略花括号,因为单行语句本身就是一个整体,无须花括号来把它们定义成一个整体。下面代码完全可以正常执行(程序清单同上):
//定义变量a ,并为其赋值
int a = 5;
if (a > 4)
//如果a>4,执行下面的执行体,只有一行代码作为代码块
System.out.println("a大于4");
else
//否则,执行下面的执行体,只有一行代码作为代码块
System.out.println("a不大于4");
通常,我们建议不要省略if、else、else if后执行块的花括号,即使条件执行体只有一行代码,因为保留花括号会有更好的可读性,而且保留花括号会减少发生错误的可能,例如如下代码,则不可正常执行:
//定义变量b ,并为其赋值
int b = 5;
if (b > 4)
//如果b>4,执行下面的执行体,只有一行代码作为代码块
System.out.println("b大于4”);
else
//否则,执行下面的执行体
b--;
//对于下面代码而言,它已经不再是条件执行体的一部分,因此总会执行
System.out.println("b不大于4");
上面代码中以粗体字标识的代码行:System.out.println("b不大于4");,将总是会执行,因为这行代码并不属于else后的条件执行体,else后的条件执行体就是b--;这行代码。if、else、else if后条件执行体要么是一个花括号扩起来的语句块,则这个语句块整体作为条件执行体;要么是以分号为结束符的一行语句,甚至可能是一个空语句(空语句是一个分号)。
如果if块后有多条语句作为条件执行体,如果省略了这个条件执行体的花括号,则会引起编译错误,看下面代码(程序清单同上):
//定义变量c ,并为其赋值
int c = 5;
if (c > 4)
//如果c>4,执行下面的执行体,将只有c--;一行代码为条件执行体
c--;
//下面是一行普通代码,不属于条件执行体
System.out.println("c大于4");
//此处的else将没有if语句,因此编译出错
else
//否则,执行下面的执行体,只有一行代码作为代码块
System.out.println("c不大于4");
在上面代码中,因为if后的条件执行体省略了花括号,则系统只把c--;一行代码作为条件执行体,当c-;语句结束后,if语句也就结束了。后面的System.out.println("c大于4");代码已经是一行普通代码了,不再属于条件执行体,从而导致else语句没有if语句,从而引起编译错误。
2.switch分支语句
switch 语句的格式:
switch ( 整型或字符型变量 ){
case 变量可能值1:
分支一;
break;
case 变量可能值2:
分支二;
break;
case 变量可能值3:
分支三;
break;
...
default :
最后分支;
}
例如:源文件:TestSwitch.java
public class TestSwitch{
public static void main(String[] args){
//声明变量score,兵为其赋值为c
char grade=c;
//执行switch分支语句
switch(grade){
case a:
System.out.println(“优秀”);
break;
case b:
System.out.println(“良好”);
break;
case c:
System.out.println(“及格”);
break;
case d:
System.out.println(“不及格”);
break;
default:
System.out.println(“输入错误”);
}
}
}
运行上面程序,看到输出结果为“及格”,这个结果完全正常,字符表达式score的值为c,对应结果为“及格”。
在switch语句中控制表达式的类型只能是byte、short、int、char和String类型。在case标签后的每个代码块后都有一条break语句,这个break,语句有极其重要的意义,java的switch语句允许省略case后代码的break语句,但这种省略可能引入一个陷阱。如果我们把上面程序中的break,运行结果会出现“及格 不及格 输入错误”。
这个运行结果看起来比较奇怪,但这正是有switch语句的运行流程决定的:switch语句会先求出expression表达式的值,然后拿这个表达式和case标签后的值进行比较,一旦遇到相等的值,程序开始执行这个case标签后代码,不再判断与后面case、default标签的条件是否匹配,除非遇到break才结束。
三、循环语句
循环语句可以在满足循环条件情况下,反复执行某一段代码,这段被重复执行的代码块被称为循环体,当反复执行这段循环体时,需要在适当的时候把循环条件改为假,从而结束循环,否则循环将一直执行下去,形成死循环,循环语句可能包含四个部分:
(1)初始化语句:一条或多条语句,这些代码用于完成一些初始化工作,初始化语句再循环开始之前执行。
(2)循环条件:这是一个boolean表达式,这个表达式能决定是否执行循环体。
(3)循环体:这个部分是循环的主体,如果循环条件允许,这个代码块将被重复执行。如果这个代码块只有一行语句,则这个代码块的花括号是可以省略的。
(4)迭代语句:这个部分在一次循环体执行结束后,对循环条件求值之前执行通常用于控制循环条件中的变量,使得循环在合适时候结束。
上面4个部分只是一般分类,并不是每个循环中都非常清晰地分出了上面4个成分。
1.while循环语句
While循环的语法格式如下:
while(循环条件){
循环体;
}
例如:
源文件:TestWhile.java
public class TestWhile.java{
public static void main(String[] args){
//循环的初始化条件
int i=0;
//当i小于10时,执行循环体
while(i<10){
System.out.print(i+“\t”);
//迭代语句
i++;
}
System.out.println(“\n 循环结束!”);
}
}
输出结果:
<pre name="code" class="java"> D:\java\java TestWhile
0 1 2 3 4 5 6 7 8 9
循环结束!
如果while循环的循环体部分和迭代语句合并在一起,且只有一行代码,则可以省略while循环后的花括号。但这种省略花括号的做法,可能降低程序的可读性。对于初学者而言,有时会出现死循环,这是在定义时出了错误,例如:
int i=0;
while(i<10){
System.out.println(“不停执行的死循环”+i);
i--;
}
在上面的代码中,i的值越来越小,i的值永远小于10,从而导致循环永远无法结束。
2.do while循环语句
do while循环与while循环的区别在于:while循环是先判断循环条件,如果条件为真才执行循环体,而do while循环先执行循环体,然后判断循环条件,如果循环条件为真,则执行下一次循环,否则中止循环。
do while循环的语句格式:
do{
循环体;
}while(循环条件);
与while循环不同的是,do while循环的循环条件后必须有一个分号,这个分号表明循环结束。
例如:
源文件:TestDoWhile.java
public class TestDoWhile{
public static void main(String[] args){
//定义变量i
int i=1;
//执行do while循环
do{
System.out.println(i+”\t”);
//循环迭代语句
i++;
}
//循环条件紧跟while关键字
while(i<10);
}
}
输出结果:
D:\java\java TestDoWhile
1 2 3 4 5 6 7 8 9
3.for循环语句
for循环是更加简洁的循环语句,大部分情况下,for循环可以代替while循环、do while循环。
for循环的格式:
for(定义变量并初始化;循环条件;新的变量值){
循环体;
}
例如:
源文件:TestFor.java
public classTestFor{
public static void main(String[] args){
//循环的初始化条件,循环条件,循环迭代语句都在下面一行
for(int i=0;i<10;i++){
System.out.println(i+”\t”);
}
}
}
输出结果:
D:\java\java TestFor
0 1 2 3 4 5 6 7 8 9
4.嵌套循环
如果把一个循环放在另一个循环体内,那么就可以形成嵌套循环,既可以for循环嵌套while循环,也可以while循环嵌套do while循环……即各种各样类型的循环都可以作为外层循环,各类型的循环也可以作为内层循环。
当程序遇到嵌套循环时,如果外层循环的循环条件允许,则开始执行外侧循环的循环体,而内层循环将被外层循环的循环体来执行——只是内层循环需要反复执行自己的循环体而已。当内层循环执行结束、且外层循环的循环体执行结束,则再次计算外层循环的循环条件,决定是否再次开始执行外层循环的循环体。据上面分析,假设外循环n次,内循环m次,那么内循环的循环体要执行n*m次。
例如:
源文件:TestNestedLoop.java
public class TestNestedLoop{
public static void mian(String[] args){
//外层循环
for(int i=0;i<5;i++){
//内循环
for(int j=0;j<3;j++){
System.out.println(“i的值为:”+i+”j的值为:”+j);
}
}
}
}
运行结果:
i的值为:0 j的值为:0
i的值为:0 j的值为:1
i的值为:0 j的值为:2
i的值为:0 j的值为:3
……
从上面的运行结果可以看出,进入嵌套循环时,循环变量i开始为0,这时即进入了外层循环。进入外层循环后,内层循环把i当成一个普通变量,其值为0。在外层循环的当次循环里,内层循环就是一个普通循环。
实际上,在嵌套不仅可以是两层嵌套,还可以三层嵌套,四层嵌套……不论循环如何嵌套,我们都以把内层循环当成外层循环的循环体来对待,区别只是这个循环体里包含了需要反复执行的代码。
四、控制循环结构
Java 语言没有提供goto语句来控制程序的跳转,这种做法提高了程序流程控制的可读性,但降低了程序流程控制的灵活性。为了弥补这种不足,java提供了continue和break来控制循环结构。除此之外,return可以结束整个方法,当然也就结束了一次循环。
1.使用break结束循环
在某些时候,我们需要在某中条件出现时,强行终止循环,而不是等到循环条件为false。可以用break来完成。Break用于完全结束一个循环,跳出循环体,不管哪种循环,一旦在循环体中遇到break,系统完全结束该循环,开始执行循环之后的代码。
例如:
源文件:TestBreak1.java
public class TestBreak1{
public static void main(String[] args){
//一个简单的for循环
for(int i=0;i<10;i++){
System.out.println(“i的值是”+i);
if(i==2){
//执行该语句时将结束循环
break;
}
}
}
}
输出结果:
i的值是2
循环体遇到break语句,程序跳出该循环。
java语句不仅可以结束其所在的循环,还可直接结束其外层循环,此时需要在break后紧跟一个标签,这标签用于标示一个外层循环。java中的标签就是一个紧跟着英文冒号(:)的标示符。与其他语言不同,java中的标签只有放在循环语句之前才起作用。
例如:
源文件:TestBreak2.java
public class TestBreak2{
public static void main(String[] args){
//外层循环,outer作为标识符
outer:
for(int i=0;i<5;i++){
//内层循环
for(int j=0;j<3;j++){
System.out.println(“i的值为:”+i+”j的值为:”+j);
if(j==1){
//跳出outer标签所标识的循环。
break outer;
}
}
}
}
}
运行结果:
i的值为:0 j的值为:0
i的值为:0 j的值为:1
当程序从外层循环进入内层循环后,当j等于1时,程序遇到一个break outer;语句,这行代码将会导致结束outer标签指定的外层循环,而不是结束break所在的循环,所以看到上面的结果。
2.使用continue结束本次循环
Continue的功能和break有点类似,区别是continue只是终止本次循环,接着开始下一次循环。而break则是完全终止循环。可以理解为continue的作用是略过当次循环中剩下的语句,重新开始新的循环。
例如:
源文件:TestContinue1.java
public class TestContinue1{
public static void main(String[] args){
//一个简单for循环
for(int i=0;i<3;i++){
System.out.println(“i的值是”+i);
if(i==1){
//执行该语句是将略过本次循环的剩下语句
continue;
}
System.out.println(“continue后的输出语句”);
}
}
}
输出结果:
i的值是0
Continue后的输出语句
i的值是1
i的值是2
Continue后的输出语句
从上面运行结果来看,当i等于1时,程序没有输出“continue后的输出语句”字符串,因为程序执行到continue时,忽略了当次循环中continue语句后的代码。与break类似,continue后也可以紧跟一个标签,用于直接结束标签所标识循环的当次,重新开始下一次循环。
例如:
源文件:TestContinue2.java
public class TestContinue2{
public static void main(String[] args){
//外层循环
outer;
for(int i=0;i<3;i++){
if(i==1){
//内层循环
System.out.println(“i的值为:”+i+”j的值为:”+j);
if(j==1){
//跳出outer标签所标识的循环。
continue outer;
}
}
}
}
}
输出结果:
i的值为:0 j的值为:0
i的值为:0 j的值为:1
i的值为:1 j的值为:0
i的值为:1 j的值为:1
i的值为:2 j的值为:0
i的值为:2 j的值为:1
运行上面程序可以看到,循环变量的值将无法超过1,因为每当j等于1时候,continue outer语句就结束了外层循环的每次循环,直接开始下一次循环,内层循环没有机会执行完成
3.使用return结束方法
return关键字并不是专门用于跳转循环的,return的功能是结束一个方法。当一个方法执行到一个return语句时,这个方法将被结束。Java程序中大部分循环都被放在方法中执行,例如前面介绍的所有循环示范程序,一旦在循环体内执行到一个return语句,return语句会结束该方法,循环自然也随之结束。
例如:
源文件:TestReturn.java
public class TestReturn{
public static void main(String[] args){
//一个简单for循环
for(int i=0;i<3;i++){
System.out.println(“i的值是”+i);
if(i==1){
return
}
System.out.println(“return后的输出语句”);
}
}
}
输出结果:
i的值是0
Return后的输出语句
i的值是1
运行上面程序,循环只能执行到i等于1时,当i等于1时程序将完全结束(当main方法结束时,也就是java程序结束时)。从这个运行结果来看,虽然return并不是专门用于循环结构控制的关键字,但通过return语句确实可以结束一个循环,与continue和break不同的是,return直接结束整个方法,不管这个return处于多少层循环之内。