五、流程控制语句

与任何程序设计语言一样,Java使用
条件语句
循环结构确定控制流程。

5.1 块作用域

块(即复合语句)是指由若干条 Java 语句组成的语句,并用一对大括号括起来。块确定了变量的作用域。一个块可以嵌套在另一个块中,但是不能在嵌套的两个块中声明同名的变量。

public static void main(String[] args) {
    int n = 4;
    {
        // int n = 5;  不能在嵌套的两个块中声明同名的变量。
        int m = 5;
    }
}

5.2 判断(条件)语句

在这里插入图片描述

5.2.1 if语句

if(关系表达式){
	语句体;

执行流程:
首先判断关系表达式看其结果是true还是false
如果是true就执行语句体
如果是false就不执行语句体

5.1.2 if…else语句

if(关系表达式){
	语句体1;
}else{
	语句体2;
}

执行流程:
首先判断关系表达式看其结果是true还是false
如果是true就执行语句体1
如果是false就执行语句体2

5.1.3 if…else if…else语句

if(判断条件1){
	执行语句1;
}else if(判断条件2){
	执行语句2;}
...
}else if(判断条件n){
	执行语句n;
}else{
	执行语句n+1;
}

执行流程:
首先判断关系表达式1看其结果是true还是false
如果是true就执行语句体1
如果是false就继续判断关系表达式2看其结果是true还是false
如果是true就执行语句体2
如果是false就继续判断关系表达式…看其结果是true还是false

如果没有任何关系表达式为true,就执行语句体n+1

5.1.4 if语句与三元运算符的互换

public static void main(String[] args) {
       int a = 20;
       int b = 10;
       //定义变量,保存a和b的最大值
       int c;
       if (a > b){
           c = a;
       }else {
           c = b;
       }
       System.out.println("1.输出最大值为:"+c);
       //用三元运算符代替if...else判断语句,结果相同
       c = a > b ? a : b;
       System.out.println("2.输出最大值为:"+c);
   }

5.3 选择语句

在处理多个选项时,使用 if/else 结构显得有些笨拙。switch语句将从与选项值相匹配的 case 标签开始执行,直到遇到 break 语句,或者执行到 switch 语句的结束处位置。如果没有相匹配的 case 标签,而有 default 子句,就执行这个子句。
在这里插入图片描述

5.3.1 选择语句–switch

switch 语句用来判断变量与多个值之间的相等性。变量的类型可以是 byte、short、int、long,或者对应的包装器类型 Byte、Short、Integer、Long,以及字符串和枚举类型。

需要注意的点:

  1. 变量可以有 1 个或者 N 个值;
  2. 值的类型必须和变量类型是一致的,并且值是确定的;
  3. 值必须是唯一的,不能重复,否则编译会出错;
  4. break 关键字是可选的,如果没有就执行下一个 case;如果有就跳出 switch 语句;
  5. default 关键字也是可选的。
switch(表达式){
	case常量值1:
		语句体1;
		break;
	case常量值2:
		语句体2;
		break;
	...
	default:
		语句体n+1;
		break;
}

执行流程:
首先计算出表达式的值
其次,和case依次比较,一旦有对应的值,就会执行相应的语句,在执行的过程中,遇到break就会结束。
最后,如果所有的case都和表达式的值不匹配,就会执行default语句体部分,然后程序结束掉。

5.3.2 case标签

case标签可以是:

  • 类型为 byte、short 、int 、long 的常量表达式,或者对应的包装器类型
  • 枚举常量
  • 从 Java7 开始,case 标签还可以是字符串字面量

5.3.3 case的穿透性

在switch语句中,如果case的后面不写break,将出现穿透现象,也就是不会在判断下一个case的值,直接向后运行,直到遇到break,或者整体switch结束。这种情况相当危险,常常会引发错误。

public static void main(String[] args) {
       int a = 5;
       switch (a){
           case 0:
               System.out.println("执行case0");
               break;
           case 5:
               System.out.println("执行case5");
           case 10:
               System.out.println("执行case10");
           default:
               System.out.println("执行default");
       }
       /*最后程序执行结果是
        执行case5
       执行case10
       执行default*/
   }

小贴士:
上述程序中,执行case5后,由于没有break语句,程序会一直向后走,不会在判断case,也不会理会break,直接运行完整体switch。由于case存在穿透性,因此初学者在编写switch语句时,必须要写上break。

5.4 循环语句

在这里插入图片描述

5.4.1 for循环

for 循环语句时支持迭代的一种通用结构,由一个计数器或类似的变量控制迭代次数,每次迭代后这个变量将会更新。

规则:for 语句的 3 个部分应该对同一个计数器变量进行初始化、检测和更新。在 for 语句内部定义的变量只能在块作用域中使用。
在这里插入图片描述

for 循环有三种循环格式:
在这里插入图片描述

  • 普通 for 循环

    普通 for 循环可以分为 4 个部分:

    1. 初始变量:循环开始执行时的初始条件。
    2. 条件(可选的):循环每次执行时要判断的条件,如果为 true,就执行循环体;如果为 false,就跳出循环体;如果没有条件,就会一直循环。
    3. 循环体:循环每次要执行的代码块,直到条件变为 false。
    4. 自增/自减:初始变量变化的方式。
    for(初始化表达式①;布尔表达式②;步进表达式④){
    	循环体③
    }
    

    执行流程:
    执行顺序:①②③④>②③④>②③④…②不满足为止。
    ①负责完成循环变量初始化
    ②负责判断是否满足循环条件,不满足则跳出循环
    ③具体执行的语句
    ④循环后,循环条件所涉及变量的变化情况

  • for-each 循环

    for-each 循环通常用于遍历数组和集合,它的使用规则比普通的 for 循环还要简单,不需要初始变量、不需要条件、不需要下标来自增或自减。

    for(元素类型 元素 : 数组或集合){
    	// 要执行的代码
    }
    
  • 无限 for 循环

    没有初始变量、没有循环条件、没有循环体,程序一旦运行起来,就停不下来,除非强制停止。

    for(;;){
    }
    

5.4.2 while循环

在这里插入图片描述

初始化表达式①
while(布尔表达式②){
	循环体③
	步进表达式④
}

执行流程:
执行顺序:①②③④>②③④>②③④…②不满足为止。
①负责完成循环变量初始化。
②负责判断是否满足循环条件,不满足则跳出循环。
③具体执行的语句。
④循环后,循环变量的变化情况。

如果把 while 循环的条件设置为 true,并且循环体中没有 break 关键字的话,程序一旦运行起来,就停不下来。除非强制停止。

5.4.3 do…while循环

do…while 循环需要循环体(一个语句块)至少执行一次,然后再检测循环条件。
在这里插入图片描述

初始化表达式①
do{
	循环体③
	步进表达式④
}while(布尔表达式②);

执行流程:
执行顺序:①③④>②③④>②③④…②不满足为止。
①负责完成循环变量初始化。
②负责判断是否满足循环条件,不满足则跳出循环。
③具体执行的语句
④循环后,循环变量的变化情况

public static void main(String[] args) {
    //使用循环输出10次HelloWorld
    //1.for循环
    for (int i = 0;i < 10;i++){
        System.out.println("HelloWorld"+i);
    }
    //2.while循环
    int j = 1;
    while (j <= 10){
        System.out.println("HelloWorld"+j);
        //步进表达式
        j++;
    }
    //3.do...while循环
    int x = 1;
    do {
        System.out.println("HelloWorld"+x);
        x++;
    }while (x <= 10)
}

5.4.4 嵌套循环

所谓嵌套循环,是指一个循环的循环体是另一个循环。比如for循环里面还有一个for循环,就是嵌套循环。总共的循环次数=外循环次数*内循环次数

for(初始化表达式①;循环条件②;步进表达式⑦){
	for(初始化表达式③;循环条件④;步进表达式⑥){
		执行语句⑤;
	}
}

执行流程:
执行顺序:①②③④⑤⑥>④⑤⑥>⑦②③④⑤⑥>④⑤⑥
外循环一次,内循环多次。
比如跳绳:一共跳5组,每组跳10个。5组就是外循环,10个就是内循环。

public static void main(String[] args) {
        //使用嵌套循环,打印5*8的矩形
        //5*8的矩形,打印5行*号,每行8个
        //外循环5次,内循环8次
        for (int i = 0;i < 5;i++){
            for (int j = 0;j < 8;j++){
                System.out.print("*");
            }
            //内循环打印8个*后,需要一次换行
            System.out.println();
        }
    }

5.4.5 死循环

死循环:也就是循环中的条件永远为true,死循环的是永不结束的循环。例如:while(true){}。

5.5 中断控制流程语句

5.5.1 break

break 关键字通常用于中断循环或 switch 语句,它在指定条件下中断程序的当前流程。如果是内部循环,则仅中断内部循环。

可以将 break 关键字用于所有类型循环语句中,比如:for 循环、while 循环、do-while 循环。

5.5.2 continue

continue 关键字用于结束本次循环,继续下一次的循环。

当我们需要在 for 循环或者 (do)while循环中立即跳转到下一个循环时,就可以使用 continue 关键字。通常用于跳过指定条件下的循环体,如果循环时嵌套的,仅跳过当前循环。

public static void main(String[] args) {
    for (int i = 1;i <= 10;i++){
        if (i == 3){
            /*
            break;
            输出 HelloWorld1 HelloWorld2
            */
            /*
            continue;
            输出 除了 HelloWorld3 全部输出
            */
        }
        System.out.println("HelloWorld"+i);
    }
}