---
url: /doc/Java/sp3j726q/index.md
---
# 4 程序控制结构

主要有顺序控制、分支控制、循环控制。

## 顺序控制

程序从上到下逐行执行，中间没有任何判断和跳转（默认的控制顺序）

比如：Java 定义变量时采用合法的前向引用。

语句：Java 中最小的执行单位。语句分为 单语句 和 复合语句。

* 单语句：通常意义的一条语句。语句间以分号 `;` 分隔。

* 复合语句：一对大括号括起来的语句组。也称为 “块”

  ```java
  {
      语句1;
      语句2;
      ...
  }
  ```

  块中可以有多条语句。块后没有分号 `;`

## 分支控制 `if-else`

> 让程序有选择的执行。主要分为：单分支控制、双分支控制

### 单分支控制

```
if (条件表达式) 语句;
JAVA
```

特别地，把代码块（复合语句）作为语句的场合也能这样写：

```
if (条件表达式) {
 执行代码块;
}JAVA
```

当条件表达式为 `ture`，就会执行 `{执行代码块;}`；如果为 `false` 则不执行。特别地：如果 `{执行代码块;}` 中只有一条代码，也可以不写 `{ }`（但还是建议写上）

### 双分支控制

```
if (条件表达式) {
 执行代码块;
} else {
 执行代码块2;
}JAVA
```

当条件表达式为 `ture`，就会执行 `{执行代码块1;}`；如果为 `false` 则执行 `{执行代码块2;}`。

### 多分支控制

```
if (条件表达式) {
 执行代码块;
} else if (条件表达式2) {
 执行代码块2;
} else if (条件表达式3) {
 执行代码块3;
}
...
else {
 执行代码块n；
}JAVA
```

特别地：多分支可以没有 `else`。此时如果条件都不成立，则无执行入口

### 嵌套分支

> 在一个分支结构中又完整嵌套了另一个完整的分支结构。里面的分支称为内层分支，外面的分支称为外层分支。

Java 规定，else 子句属于逻辑上距其最近，且没有匹配 else 的 if 语句：

> ```
> int n = 0;
> if (n > 0) n++;
> if (n > 1) n++;
> else n--;			//属于上面这个 if 语句JAVA
> ```
>
> 这个场合，这个 else 语句属于上面的 `if (n > 1)` 这个语句

要想改变那个匹配关系，要使用 `{ }` 改变语句结构：

> ```
> int n = 0;
> if (n > 0) {
>     n++;
> 	if (n > 1) n++;
> } else n--;JAVA
> ```

**规范：嵌套尽量不超过 3 层（可读性不好）**

## `switch` 分支结构

```
switch(表达式){
	case 常量1:
		语句块1;
		break;			//break 语句可选
	case 常量2:
		语句块2;
		break;			//break 语句可选
	...
	default:			//default 语句可选
		default语句块;
		break;			//break 语句可选
}JAVA
```

1. `switch` 关键字，表示 switch 分支。
2. `表达式` 对应一个值。**该值必须是 int 或 char**（char 可以转化为 int）。是 byte 或 short 的场合，要提升为 int。不允许 long、double 或 float
3. `case 常量1;` 表示：当 `表达式` 的值等于 `常量1` ，则执行 `语句块1`。
4. `break;` 表示退出 switch 分支。
5. 当 `表达式` 的值匹配 `常量1` ，则执行 `语句块1`，如果不匹配，则继续匹配 `常量2` ，以此类推。
6. 如果全都不匹配，则执行 `default`。
7. 如果不写 `break;` ，则会发生**穿透**，即不进行判断而继续执行下一语句块。

### 使用细节

1. `表达式;` 数据类型，应和 `case` 后的 `常量` 类型一致，或者是可以自动转换成可以比较的类型。如：输入的是 `char` 而 `常量` 是 `int`

2. switch 中 `表达式` 的返回值必须是：`byte` `short` `int` `char ``enum` `String`

   ***——`enum` 是什么？详见 \[\[10.1 枚举 ]]\(https://i-melody.github.io/2021/12/17/Java/入门阶段/10 枚举和注解/#10-1-枚举)***

3. `case` 语句中的值必须是 常量 或 常量表达式，不能是 变量。

4. `default` 是可选的。没有就不执行。

5. `break;` 用来跳出 switch 分支。如果不写，会持续执行语句，直到分支结束或遇到下一个 `break;`

### 4.3.2 与 `if-else` 分支结构的取舍

* 如果判断的具体数值不多，且符合 ***\[\[4.3.1.1]]\(https://i-melody.github.io/2021/11/24/Java/入门阶段/4 程序控制结构/#4-3-1-使用细节)*** ，推荐使用 switch。
* 对区间判断的场合，对结果为 boolean 类型的判断，使用 `if-else`。

## `for` 循环控制

> 让代码可以循环执行。

```
for(循环变量初始化;循环条件;循环变量迭代){
循环操作（代码块）;
}JAVA
```

* `for` 关键字，表示循环控制
* 四个要素：1. 循环变量初始化 2. 循环的条件 3. 循环的操作 4. 循环变量迭代

所有循环开始前仅一次进行初始化。直到循环条件变为 false 前，执行循环操作。每轮循环结束后，进行循环变量迭代。

* 循环操作可以有多条语句
* 如果循环操作只有一条语句，可以省略 `" "`，但建议不省略

### 使用细节

1. 循环条件是返回一个 boolean 值（`ture` 或 `false`）的公式。

   循环条件可以为空。这个场合，默认为真（true）

2. `for(;循环条件;){ }` 其中的初始化和变量迭代可以写在别处，但 `;` 不能省略。如果不写在别处，那个 `循环变量初始化` 中声明的变量只能在该 for 循环中使用。

3. 控制台用 ctrl + c 强制结束一个流程

4. 循环初始值可以有多条初始化语句，但要求类型一样，并用 `,` 隔开。

   变量迭代也可以有多条代码，用 `,` 隔开。

### for each（泛型 for 循环）

> 泛型 for 循环（增强 for 循环）能用来依次处理数组（或其他元素集合）中的每个元素，而不必考虑下标值

```
for(int i : nums){						//其中 nums 是一个一维 int 数组
	System.out.println(i);
}JAVA
```

上述写法（增强 `for` 写法）类似于以下写法

```
for(int i = 0; i < nums.length; i++){
	System.out.println(nums[i]);
}JAVA
```

泛型 for 循环适用于数组或一个实现了 Iterable 接口的对象。泛型 for 循环的本质是一个 Iterator（迭代器）

***—— 迭代器，见 \[\[13.2.2.1 用 Iterator 遍历元素]]\(https://i-melody.github.io/2021/12/22/Java/入门阶段/13 集合/#13-2-2-2-用-enhanced-for-遍历元素)***

## `while` 循环控制

```
while(循环条件){
 循环体(代码块);
 循环变量迭代;
}JAVA
```

`while` 也有四要素，只是位置和 `for` 不同

### 使用细节

1. 循环条件是返回一个 boolean 值（`ture` 或 `false`）的公式。

   while 循环中，循环条件不能为空。

2. `while` 循环是先判断再执行语句。

## `do..while` 循环控制

```
do{
循环体;
循环变量迭代;
}while(循环条件);JAVA
```

1. `do` `while` 是关键字
2. 也有四要素，位置不同
3. 先执行，再判断。也就是说，一定会至少执行一次
4. **最后有一个 `;`**
5. `while` 与 `do..while` 区别：“要账”

### 使用细节

1. 循环条件是返回一个 boolean 值（`ture` 或 `false`）的公式。
2. `do..while` 循环是先执行再判断的语句。因此至少执行一次。

## 多重循环控制

将一个循环放在另一个循环体内，就形成了嵌套循环。建议一般使用两层，最多不超过三层。

嵌套循环 是把 内层循环 当成 外层循环 的 循环体。只有内层 `false` 时才可能结束当层循环。

若内层执行 n 次，外层 m 次，则合计会循环 n\*m 次

以下是一个示例（乘法口诀）

```java
>public class Code4_7{
   public static void main(String[] args){
          int a = 1;	//声明第一个乘数
      		int b = 1;	//声明第二个乘数
           do{
               //直到 a > b 为止，a 不断增长，并让两数相乘，输出公式
          do{
                   System.out.print(a + " * " + b + " = " + a * b + "\t");
                   a++;
               } while (a <= b);
               //把 a 重置为 1，让 b 增长，然后循环
           a = 1;
           System.out.println();
           b++;
      } while (b <= 9);
   }
}
```

## 4.8 跳转控制语句

> 跳转控制语句用于分支或循环中，以便程序员更好控制程序执行方向

### 4.8.1 标签

```java
a:{
b:	{
c:		{
   ...
		 berak b;
		}
	}
}
```

1. `a:` `b:` `c:` 是标签，名字由程序员指定
2. `break` 后指定哪个标签就退出到哪里
3. **实际开发中，尽量不要使用标签**

### break

> 用于中止一个语句块的执行

语法：`break;`

break 可以被用在三种场合中

* switch 语句中，以跳出判断（结束穿透）

* for、while、do…while 循环语句中，以跳出循环

* 语句块中，以跳过本块中所有剩余语句

  `break` 语句出现在多层嵌套的语句块中时，可以通过 **标签** 指明要终止的时哪一层语句块。

### continue

> 在循环中出现。用于结束本次循环，继续下一次循环

语法：`continue;`

进行下次循环前，仍会判断循环条件是否满足

在多层嵌套循环中，可以通过标签指出跳出哪次循环（同 `break`）

### return

> 用于方法。表示跳出所在的方法

语法：`return;`

方法有返回值的场合，将返回值写在 return 后：`return 值;`

如果写在 主方法 则跳出程序
