第三章 流程控制语句

1、表达式和语句

  • 语句分为单语句和复合语句
    • 单语句是指,一条具体的可被执行的代码指令。比如,给变量赋值,变量相加减后赋值、调用某个方法如打印,等等。每一个单语句结束时都由分号 ; 表示结束。
    • 复合语句是指,有多个单语句组成的一段代码整体,这一段代码要么都不执行,要么作为一个整体都执行,为了标识它们为一个整体,通常用 {} 将这些语句包括起来。
  • 表达式
    • 表达式是指可以被求值的代码,比如 1 + 2,3 * 5,a * b 等等具有值的式子被称为表达式
    • 1 < 2,它的值是 true,所以 1 < 2 也是一个表达式
    • 只要可以求值的式子都是表达式。

2、顺序结构

​ 任何编程语言中最常见的程序结构就是顺序结构。顺序结构就是程序从上到下逐行地执行,中间没有任何判断和跳转。

​ 如果 main 方法的多行代码之间没有任何流程控制,则程序总是从上向下依次执行,排在前面的代码先执行,排在后面的代码后执行。这意味着:如果没有流程控制,Java 方法里的语句是一个顺序执行流,从上向下依次执行每条语句。

3、分支语句

​ Java 提供了两种常见的分支控制结构:if 语句和 switch 语句,其中 if 语句使用布尔表达式或布尔值作为分支条件来进行分支控制;而 switch 语句则用于对多个整型值进行匹配,从而实现分支控制。

3.1、单分支条件判断

语法格式:

1
2
3
4
5
if(表达式){
语句;
语句;
...

执行流程

  • 首先判断条件表达式看其结果是 true 还是 false
  • 如果是 true 就执行其中的代码块
  • 如果是 false 就不执行代码块

在下面的示例中,我们测试两个值以确定20是否大于18。如果条件为真,则打印一些文本:

1
2
3
4
5
6
7
8
9
10
11
12
13
if (20 > 18) {							//表达式的值为 true
System.out.println("20 比 18 大"); //执行输出
}

if (20 < 18) { //表达式的值为 false
System.out.println("20 比 18 小"); //不执行输出
}

int x = 20;
int y = 18;
if (x > y) {
System.out.println("x 大于 y");
}

3.2、双分支条件判断

​ 当条件为 false 的时候,也可以通过使用 else 语句指定要执行的代码块。

1
2
3
4
5
6
7
if (表达式) {
// 如果条件为真,将执行的代码块
语句1;
} else {
// 如果条件为假,将执行的代码块
语句2;
}

执行流程

​ 在下面的例子中,time 为 20 大于 18,因此条件为 false。因此,我们将执行 else 条件,并向屏幕输出“Good evening”。如果时间小于18,程序将打印“Good day”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int time = 20;
if (time < 18) {
System.out.println("Good day.");
} else {
System.out.println("Good evening.");
}
// 输出 "Good evening."

time = 10;
if (time < 18) {
System.out.println("Good day.");
} else {
System.out.println("Good evening.");
}

// 输出 "Good day."

3.3、多分支条件判断

语法格式:

1
2
3
4
5
6
7
if (表达式1) {
// 若表达式1为真,则执行此处代码
} else if (表达式2) {
// 如果表达式1为假,表达式2为真,则执行此处代码
} else {
// 若表达式1和表达式2都为假,则执行此处代码
}

注:多分支中,可以在 if 和 else 之中有很多个 else if

执行流程

案例:

1
2
3
4
5
6
7
8
9
10
11
int time = 22;
if (time < 10) {
System.out.println("Good morning.");
} else if (time < 18) {
System.out.println("Good day.");
} else if (time < 30) {
System.out.println("Good afternoon.");
} else {
System.out.println("Good evening.");
}
// 输出 "Good afternoon."

​ 在上面的案例中,我们按顺序判断条件,首先判断 if 中的表达式,为 false 就接着判断第一个 else if 中的表达式,也为 false 又继续判断下一个 else if ,为 true 就执行其中代码,后续就不再判断了。只要 true 出现了就不继续判断,如果 if 和所有 else if 中的表达式都为 false,则实现 else 中的代码。

3.4、if else 嵌套结构

​ 在 if 的语句块中,或者是在else if 和 else 语句块中,又包含了另外一个条件判断(可以是单分支、双分支、多分支)。

语法结构

1
2
3
4
5
6
7
8
9
10
11
12
if (表达式1) {
// 嵌套一个条件判断语句
if (){

} else {

}
} else if () {
// 这里也可以嵌套
} else {
// 这里也可以嵌套
}

3.5、Switch…case…多分支选择结构

​ 可以使用 switch 语句替代需要编写许多 if…else 语句的代码。

语法格式:

1
2
3
4
5
6
7
8
9
10
11
switch(表达式) {
case 常量值1:
// code block
break;
case 常量值2:
// code block
break;
// 这里可以有很多的 case 语句
default:
// code block
}

注:case 后面必须是常量值,而且不能重复

执行流程:

  • switch 表达式求值一次。

  • 将表达式的值与每个case的值进行比较。

  • 如果存在匹配,则执行相关的代码块。

  • break 表示终止 switch 的后续匹配行为。

  • default 表示如没有匹配的值,则执行 default 中的代码。

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int day = 4;
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thursday");
break;
case 5:
System.out.println("Friday");
break;
case 6:
System.out.println("Saturday");
break;
case 7:
System.out.println("Sunday");
break;
default:
System.out.println("没有匹配的值");
}
// 输出 "Thursday" (day 4)
// 如果 day = 6 则输出 "Saturday"
// 如果 day = 100,没有匹配的值,则执行 default 中的代码块,输出 "没有匹配的值"

4、循环语句

​ 循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复执行这个循环体时,需要通过修改循环变量使得循环判断条件为 false,从而结束循环,否则循环将一直执行下去,形成死循环。

4.1、while 循环

基本语句格式:

1
2
3
while (表达式) {
循环体语句;
}

注:while 循环中表达式必须要是 boolean 布尔类型的值

执行流程:

  • 第一步:计算表达式,看表达式的值是 true,还是 false;
    • 如果是 true,执行第二步;
    • 如果是 false,循环语句中止,循环不再执行。
  • 第二步:执行循环体语句;
  • 第三步:循环体语句执行完后,重新从第一步开始再执行一遍

案例:

1
2
3
4
5
6
7
8
//循环的初始化条件
int i = 0;
//当 i 小于10时,执行循环体
while (i < 10) {
System.out.println(i);
//迭代语句
i++;
}

​ 使用while循环时,一定要保证循环条件有变成 false 的时候,比如上述代码中的 i++,它可以一直加到等于10,是条件表达式值变为了 false,从而使循环停止,否则这个循环将成为一个死循环,永远无法结束这个循环。我们将能够使条件表达式值更新的语句称为迭代语句。

4.2、do…while 循环

​ do…while 循环是 while 循环的一种变体。在检查条件是否为真之前,这个循环将先执行代码块一次,然后只要条件为真,它就重复这个循环。

语法格式:

1
2
3
do {
循环体语句;
} while (表达式);

注:do{ } while( ); 最后有一个分号

重要区别:do…while 循环无论如何都会先执行一次循环体中的代码

执行流程:

  • 第一步:执行循环体语句;
  • 第二步:执行循环条件表达式,看表达式的值是 true,还是 false;
    • 如果是 true,执行第三步;
    • 如果是 false,循环语句终止,循环不再执行。
  • 第三步:循环条件语句执行完后,重新从第一步开始再执行一遍。

案例:

1
2
3
4
5
6
int i = 10;
do {
System.out.println(i);
i++;
}
while (i > 10 && i < 20);

​ 即使一开始 do…while 中的表达式为 false,但是还是无论如何都会执行一次循环体,使得 i = 11,从而使得表达式变为 true。

简单来说,就是先判断再执行 还是 先执行再判断的问题。

4.3、for 循环

当你确切地知道要在代码块中循环多少次时,请使用 for 循环而不是 while 循环

语法格式:

1
2
3
for(初始化语句; 循环条件表达式; 迭代语句){
循环体
}

注:for(;;)中的两个;不能多也不能少。

  • 初始化语句 - 初始化语句在执行代码块之前执行一次,之后循环时不会再执行
  • 循环条件表达式 - 每次循环检查一次条件表达式是否为 true
  • 迭代语句 - 在每次循环结束时都要执行一次这个语句

执行流程:

  1. 执行初始化语句,完成循环变量的初始化;
  2. 执行循环条件表达式,看循环条件表达式的值是true,还是false;
    • 如果是true,执行第三步;
    • 如果是false,循环语句中止,循环不再执行。
  3. 执行循环体语句
  4. 执行迭代语句,针对循环变量重新赋值
  5. 根据循环变量的新值,重新从第二步开始再执行一遍

案例:

1
2
3
4
// for (语句1; 语句2; 语句3){}
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
  • 语句1 在循环开始前设置一个变量( int i = 0 )。

  • 语句2 定义了循环运行的条件( i必须小于5 )。如果条件为真,循环将重新开始,如果为假,循环将结束。

  • 语句3 每执行一次循环中的代码块,就增加一个值 ( i++ )。

4.4、循环的嵌套

​ 我们也可以将一个循环放入另一个循环中,这被称为嵌套循环。“内循环” 将在 “外循环” 的每次循环中执行一次:

1
2
3
4
5
6
7
8
9
// 外循环
for (int i = 1; i <= 2; i++) {
System.out.println("外: " + i); // 执行 2 次

// 内循环
for (int j = 1; j <= 3; j++) {
System.out.println(" 内: " + j); // 执行 6 次 (2 * 3)
}
}

执行特点:外循环执行一次,内循环执行一轮。

4.5、break 关键字

​ 在某些时候,我们需要在某种条件出现时强行终止循环,而不是等到循环条件为false时才退出循环。此时,可以使用break来完成这个功能。break用于完全结束一个循环,跳出循环体。不管是哪种循环,一旦在循环体中遇到break,系统将完全结束该循环,开始执行循环之后的代码。

案例:

1
2
3
4
5
6
for (int i = 0; i < 10; i++) {
if (i == 4) {
break;
}
System.out.println(i);
}

这个例子会在 i 等于4时停止循环。

4.6、continue 关键字

​ continue的功能和break有点类似,区别是continue只是终止本次循环,接着开始下一次循环;而break则是完全终止循环本身。可以理解为continue的作用是跳过当次循环中剩下的语句,重新开始一次新的循环。例如,如下程序示范了continue的用法。

案例:

1
2
3
4
5
6
for (int i = 0; i < 10; i++) {
if (i == 4) {
continue;
}
System.out.println(i);
}

这个例子会在 i == 4 是提前结束,不执行后面的打印操作,直接继续开始执行 i == 5 时的循环操作。

5、变量的作用域

​ 我们已经知道,对于复合语句我们需要用 {} 大括号将它们包括起来,{} 之中定义的变量无法在 {} 括号之外被访问,只能在 {} 之内访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class TestForVariableScope {
public static void main(String[] args) {
int mainVar = 0;
int i = 0;

if (i < 5) {
int a = 10;
while(a < 20) {
int b = 100;
a++;

System.out.println(mainVar);
System.out.println(a);
System.out.println(i);
System.out.println(b);
}

System.out.println(mainVar);
System.out.println(a);
System.out.println(i);
// System.out.println(b); 无法访问
}

System.out.println(mainVar);
// System.out.println(a); 无法访问
// System.out.println(b); 无法访问
}
}
  • mainVar 和 i 变量在 main 方法这个 {} 中定义的,则在这个 main {} 中的所有地方都能访问这两个变量,而 if 和 while 语句都在 main {} 中,所以在其中也可以使用这两个变量。
  • a 变量在 if 之中定义,所以在 if 的 {} 之外无法使用,而在 {} 之内的 while 语句可以使用。