一、程序的三种基本结构

结构 作用 本章用到的语句
顺序结构 按代码顺序执行 普通语句
分支结构 根据条件选择执行哪些代码 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; } 

执行过程:

  1. 计算 switch 括号内表达式的值。
  2. 找到与该值相等的 case,从对应位置开始执行。
  3. 遇到 break,退出当前 switch,执行其后的代码。
  4. 没有匹配的 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 结束循环 

上例中:

  1. num 为 1,满足条件,输出 1,再变成 2。
  2. 重复判断、输出、自增,直到输出 10。
  3. 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

理解嵌套循环时,抓住三点:

  1. 外层每执行一轮,内层都要完整执行一遍。 不是外层走一步、内层走一步。
  2. factorial 放在外层循环内部,每次计算新的阶乘前重置为 1;内层的 j 也重新从 1 开始。
  3. 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。