一、程序的三种基本结构
| 结构 | 作用 | 本章用到的语句 |
|---|---|---|
| 顺序结构 | 按代码顺序执行 | 普通语句 |
| 分支结构 | 根据条件选择执行哪些代码 | if、switch |
| 循环结构 | 重复执行一段代码 | while、for |
顺序结构就是从上往下执行,调整语句的位置,执行顺序也会改变。
System.out.println("aaa"); System.out.println("bbb"); System.out.println("ccc"); 以上代码依次输出 aaa、bbb、ccc,每次输出后换行。
下文 Java 示例彼此独立,放在 main 方法中即可运行;标为错误的示例仅用于分析。
public class Main { public static void main(String[] args) { // 将要运行的示例放在这里 } } 二、if:根据条件决定执行哪条分支
if 括号中的条件必须得到 boolean 结果,即 true 或 false,不能直接用整数代替。
2.1 单分支:满足条件才执行
int score = 92; if (score >= 90) { System.out.println("优秀"); } System.out.println("判断结束"); - 条件为
true:执行{}内的代码,再继续往下执行。 - 条件为
false:跳过{},继续往下执行。
因此,无论成绩是多少,最后都会输出“判断结束”。
2.2 双分支:两个分支选一个
int num = 10; if (num % 2 == 0) { System.out.println("偶数"); } else { System.out.println("奇数"); } 条件成立执行 if 分支,否则执行 else 分支,两者只执行一个。else 后面不写条件。
判断奇偶时用 num % 2 == 0 判断偶数,其余为奇数,负整数也适用。
2.3 多分支:从上往下,命中一个就结束选择
int num = -3; if (num > 0) { System.out.println("正数"); } else if (num < 0) { System.out.println("负数"); } else { System.out.println("零"); } 执行规则:依次判断,遇到第一个成立的条件就执行对应分支,后面的条件不再判断。全部不成立时,执行最后的 else;如果没有 else,则整个分支结构不执行任何分支。
注意:多个独立的 if 会分别判断,可能执行多个分支;if-else if 链最多执行一个分支。
示例:按分数划分等级
int score = 85; if (score < 0 || score > 100) { System.out.println("错误数据"); } else if (score >= 90) { System.out.println("优秀"); } else if (score >= 80) { System.out.println("良好"); } else if (score >= 70) { System.out.println("中等"); } else if (score >= 60) { System.out.println("及格"); } else { System.out.println("不及格"); } 先排除不在 0~100 范围内的数据,避免把 101 也判断为优秀。
为什么第二个等级只写 score >= 80,不用再写 score < 90?
因为能走到这里,就说明前面的 score >= 90 不成立。此时已经确定分数小于 90,所以这一分支实际对应的是 80 ≤ score < 90。
按“从高到低”的顺序判断,前面的条件会帮助后面的分支缩小范围。 如果先判断 score >= 60,那么 95 也会先进入这一分支。
2.4 嵌套 if:先判断大条件,再判断小条件
判断闰年的规则:
- 能被
100整除的年份,还必须能被400整除。 - 不能被
100整除的年份,能被4整除即可。
int year = 2000; if (year % 100 == 0) { if (year % 400 == 0) { System.out.println("闰年"); } else { System.out.println("平年"); } } else { if (year % 4 == 0) { System.out.println("闰年"); } else { System.out.println("平年"); } } 例如:2000 是闰年,1900 是平年,2024 是闰年。只判断能否被 4 整除,会误判 1900。
2.5 大括号和分号:两个常见错误
1. 省略大括号时,分支只控制紧跟着的一条语句。
嵌套时,else 与前面最近的、尚未匹配 else 的 if 配对,缩进不能改变配对关系。
int x = 10; int y = 20; if (x == 10) if (y == 10) System.out.println("A"); else System.out.println("B"); 这里的 else 属于 if (y == 10),所以输出 B。如果 x 不等于 10,则什么也不输出。
实际写代码时统一加 {},并把左大括号放在 if、else 所在行,明确每个分支的范围。
2. 不要在 if (条件) 后多写分号。
// 错误示例:本想条件成立才输出,却多写了分号 int x = 20; if (x == 10); { System.out.println("A"); } 这个分号本身就是一条“什么也不做”的空语句,成为了 if 控制的内容。后面的 {} 已经与 if 无关,因此即使条件为 false,也会输出 A。
三、switch:根据一个值选择分支
3.1 基本写法与执行过程
switch 适合“一个值对应多个固定选项”的场景,例如根据数字输出星期。
int day = 3; switch (day) { case 1: System.out.println("星期一"); break; case 2: System.out.println("星期二"); break; case 3: System.out.println("星期三"); break; case 4: System.out.println("星期四"); break; case 5: System.out.println("星期五"); break; case 6: System.out.println("星期六"); break; case 7: System.out.println("星期日"); break; default: System.out.println("输入有误"); break; } 执行过程:
- 计算
switch括号内表达式的值。 - 找到与该值相等的
case,从对应位置开始执行。 - 遇到
break,退出当前switch,执行其后的代码。 - 没有匹配的
case时,从default开始执行;如果也没有default,直接跳过整个switch。
case 后面写常量,常量值不能重复;default 用于处理未匹配的情况,可以省略。
3.2 漏写 break:会继续向下执行
int day = 1; switch (day) { case 1: System.out.println("星期一"); // 此处没有 break case 2: System.out.println("星期二"); break; default: System.out.println("输入有误"); } 输出:
星期一 星期二 匹配到 case 1 后,如果没有 break,程序会继续向下执行,不会再检查 day 是否等于 2。 这种现象叫作“贯穿”,直到遇到 break 或执行到 switch 末尾才结束。
如果只想执行一个选项,就在对应分支末尾写上 break。
3.3 类型限制与适用场景
本章沿用传统的 case 常量: 写法,先掌握课件涉及的类型:
- 基本类型:
byte、short、char、int。 - 其他类型:
String、枚举类型。
String 表示字符串,switch 中可以使用字符串变量,不局限于直接写字符串常量。枚举表示一组固定的可选值,例如星期一到星期日,本章暂不展开定义方式。
在本章所用的传统规则下,不能用 long、float、double、boolean 作为 switch 表达式的类型。
| 判断需求 | 更适合的写法 |
|---|---|
| 是否等于几个固定值,如星期编号 | switch |
范围判断,如 num > 10 && num < 20 | if |
| 多个条件组合判断 | if |
传统 case 不能直接写范围条件。switch 可以嵌套,但可读性较差,本章不展开嵌套写法。
四、while:满足条件就重复执行
4.1 先判断,再执行
int num = 1; while (num <= 10) { System.out.println(num); num++; } 执行顺序是:
初始化 → 判断条件 → 条件为 true 则执行循环体 → 回到条件判断 ↓ 条件为 false 结束循环 上例中:
-
num为1,满足条件,输出1,再变成2。 - 重复判断、输出、自增,直到输出
10。 -
num变成11,条件为false,退出循环。
每轮执行循环体之前都要判断条件。第一次判断就为 false,循环体一次也不会执行。
写循环时先想清楚三件事:从哪里开始、什么时候继续、每轮如何推进到结束条件。
4.2 累加:计算 1~100 的和
int n = 1; int sum = 0; while (n <= 100) { sum += n; n++; } System.out.println(sum); // 5050 n 表示本轮要加的数,sum 保存已经累加的结果。
- 累加器从
0开始,不影响后面的加法。 -
sum放在循环外初始化,才能保留上一轮的结果;每轮重新设为0就无法累计。 - 输出放在循环后,得到最终结果;放在循环内则会输出每一步的中间结果。
4.3 累乘:计算 5 的阶乘
5! 表示 1 × 2 × 3 × 4 × 5。
int n = 1; int result = 1; while (n <= 5) { result *= n; n++; } System.out.println(result); // 120 累加通常从 0 开始,累乘通常从 1 开始。 如果把 result 初始化为 0,之后乘任何数,结果都还是 0。
4.4 死循环:条件始终成立
上面打印数字的例子如果漏掉 num++,num 就一直是 1,程序会不停输出 1。
还有一种错误是多写分号:
// 错误示例:不要运行,循环无法结束 int num = 1; while (num <= 10); { System.out.println(num); num++; } 此时真正的循环体只有空语句 ;,后面的 {} 不属于循环。num 始终为 1,程序一直重复判断条件,既没有输出,也到不了后面的自增语句。
与 if 一样,while 的循环体建议始终加 {},条件后不要多写分号。
五、break 与 continue:结束循环还是跳过本轮
| 语句 | 在循环中的作用 | 下一步去哪里 |
|---|---|---|
break | 立即结束所在循环 | 循环后的代码 |
continue | 跳过本轮剩余代码 | 按循环规则进入下一轮 |
5.1 break:找到第一个结果就停止
找出 100~200 中第一个 3 的倍数:
int num = 100; while (num <= 200) { if (num % 3 == 0) { System.out.println(num); // 102 break; } num++; } 100、101 不满足要求,继续尝试;102 满足要求,输出后执行 break,不再检查后面的数。
这里的 break 退出的是最内层包围它的循环或 switch。 它不会因为写在 if 里面就只是退出 if,也不会一次退出所有外层循环。
5.2 continue:不符合要求就跳过本轮
找出 100~200 中所有 3 的倍数:
int num = 100; while (num <= 200) { if (num % 3 != 0) { num++; continue; } System.out.println(num); num++; } 输出 102、105、108……198,每个数占一行。
- 不是
3的倍数:先自增,再执行continue,跳过本轮的输出和末尾自增。 - 是
3的倍数:输出,再执行末尾的自增。
两条路径每轮都只自增一次。
为什么 continue 前还要写一次 num++?
因为 while 遇到 continue 后会直接回到条件判断,底部的 num++ 不会执行。若少了前面的自增,程序会一直停在 num == 100,形成死循环。
六、for:把循环的三个要素写在一起
6.1 执行顺序
for (初始化; 循环条件; 更新操作) { 循环体 } for (int i = 1; i <= 10; i++) { System.out.println(i); } 执行顺序:
初始化(只执行一次) ↓ 判断条件 ── false → 结束循环 ↓ true 执行循环体 ↓ 执行更新操作 ↓ 回到条件判断 i++ 在循环体之后执行,不是在循环体之前。 上例先输出 1,再执行自增。
for 与 while 都能完成计数、求和、求阶乘等任务。需要明确地遍历一段范围时,for 通常更直观;主要围绕某个条件反复执行时,可以用 while。
例如,求 1~100 的和:
int sum = 0; for (int i = 1; i <= 100; i++) { sum += i; } System.out.println(sum); // 5050 改成求 5! 时,把累乘结果初始化为 1,循环到 5,每轮执行 result *= i 即可。
6.2 for 中的 break 和 continue
-
break:直接退出循环,更新操作也不再执行。 -
continue:跳过本轮剩余的循环体,先执行更新操作,再判断条件。
因此,前面寻找所有 3 的倍数的代码可以写成:
for (int num = 100; num <= 200; num++) { if (num % 3 != 0) { continue; } System.out.println(num); } 这里不必在 continue 前手动自增,因为 for 头部的 num++ 仍然会执行。
6.3 注意分号和省略条件
for 括号中的两个分号是分隔符,必须保留;右括号后不要额外加分号,否则循环体会变成空语句。
省略中间的条件,相当于条件始终为 true,不会因为条件不满足而停止,但仍可以用 break 退出:
for (int i = 1; ; i++) { if (i > 3) { break; } System.out.println(i); } 这段代码依次输出 1、2、3 后结束。因此,“省略条件”并不一定代表程序永远无法退出。
七、嵌套循环:计算 1! + 2! + 3! + 4! + 5!
把任务拆成两层:
- 外层决定这一轮计算谁的阶乘,并把结果加入总和。
- 内层从
1乘到当前数字,算出这一个阶乘。
int sum = 0; for (int i = 1; i <= 5; i++) { int factorial = 1; for (int j = 1; j <= i; j++) { factorial *= j; } sum += factorial; } System.out.println(sum); // 153 执行过程:
| 外层的 i | 内层计算 | 本轮 factorial | 累加后的 sum |
|---|---|---|---|
| 1 | 1 | 1 | 1 |
| 2 | 1 × 2 | 2 | 3 |
| 3 | 1 × 2 × 3 | 6 | 9 |
| 4 | 1 × 2 × 3 × 4 | 24 | 33 |
| 5 | 1 × 2 × 3 × 4 × 5 | 120 | 153 |
理解嵌套循环时,抓住三点:
- 外层每执行一轮,内层都要完整执行一遍。 不是外层走一步、内层走一步。
-
factorial放在外层循环内部,每次计算新的阶乘前重置为1;内层的j也重新从1开始。 -
sum放在两层循环外,保留总和;sum += factorial放在内层循环结束后,因为此时这个阶乘才算完整。
while 也能嵌套,思路相同,只需手动安排好两层循环变量的初始化和更新。
do-while在课件中属于选学,使用较少,本章不展开;以上题目使用while和for即可完成。
八、综合练习
8.1 判断一个整数是否为素数
素数是大于 1,且只有 1 和自身两个正因数的整数。 0、1、负整数都不是素数。
最直接的做法是尝试用 2~num-1 中的整数去除 num:
- 只要找到一个能整除的数,就能确定不是素数,无需继续尝试。
- 全部尝试完都不能整除,才是素数。
int num = 29; boolean isPrime = true; if (num <= 1) { isPrime = false; } else { for (int i = 2; i < num; i++) { if (num % i == 0) { isPrime = false; break; } } } if (isPrime) { System.out.println("是素数"); } else { System.out.println("不是素数"); } isPrime 用来记录判断结果:先假设是素数,再用检查结果推翻这一假设。
-
num == 9:试到3时可以整除,标记为不是素数,退出循环。 -
num == 2:循环条件2 < 2一开始就不成立,保留true,正确判断为素数。 - 上界必须写
i < num,不能写i <= num,否则会把自身也作为排除依据。
不要因为某一次不能整除,就立即判定为素数。 例如 9 不能被 2 整除,但能被 3 整除。
8.2 输出 0~999 中所有水仙花数
本题中的水仙花数指:一个三位数,各位数字的立方和等于它本身。
例如:153 = 1 × 1 × 1 + 5 × 5 × 5 + 3 × 3 × 3。
虽然题目范围是 0~999,但根据“三位数”的定义,只需检查 100~999。
对三位整数 num 拆位:
| 数位 | 写法 | num = 153 时 |
|---|---|---|
| 百位 | num / 100 | 1 |
| 十位 | num / 10 % 10 | 5 |
| 个位 | num % 10 | 3 |
for (int num = 100; num <= 999; num++) { int hundreds = num / 100; int tens = num / 10 % 10; int units = num % 10; int sum = hundreds * hundreds * hundreds + tens * tens * tens + units * units * units; if (sum == num) { System.out.println(num); } } 输出:
153 370 371 407 Java 中 ^ 不是乘方运算,计算一个数的立方应写成 x * x * x,不能写成 x ^ 3。

