Skip to content

条件判断与循环 ​

学习目标 ​

  • 能根据问题选择 if、传统 switch 或 switch 表达式表达条件分支。
  • 会使用 for、增强 for、while 和 do-while,并能检查循环是否一定终止。
  • 理解 break、continue、标签和早返回的作用范围,减少不必要的嵌套。

核心知识点 ​

专业术语 ​

  • 控制流(control flow):决定语句执行顺序的分支、循环和跳转。
  • 条件分支(conditional branch):根据布尔表达式选择一条或多条执行路径。
  • switch 语句/表达式(switch statement/expression):按离散标签分类;表达式会产生一个值。
  • 迭代(iteration):重复执行一段代码;for、while 和 do-while 都是迭代结构。
  • 循环不变量(loop invariant):每轮开始前都成立的事实,有助于检查循环逻辑。
  • 守卫式返回(guard clause):先处理无效或特殊输入并立即返回,使主路径保持平坦。

白话解释与边界 ​

if、else 与早返回 ​

if 适合范围判断、组合条件和早返回。先处理无效或特殊输入并立即 return,可以把主路径保持在较浅的嵌套层级。

switch 语句与表达式 ​

switch 适合有限的离散选项,例如菜单、状态或枚举。传统 switch 的冒号分支可能继续执行下一个 case,需要 break、return 或有意利用穿透;箭头分支不会意外穿透。switch 表达式必须为每条路径产生值,通常用 default 覆盖未知输入。

for 与增强 for ​

for 适合次数或索引明确的循环,增强 for 适合遍历数组和集合。循环的初始化、条件和更新必须共同推动状态变化,否则就会无限循环。

while 与 do-while ​

while 先判断条件,可能一次也不执行;do-while 先执行再判断,至少执行一次。

break 与 continue ​

break 结束最近一层循环或 switch,continue 跳过本轮剩余代码并进入下一轮。标签可以跳出多层循环,但低频且容易降低可读性,通常提取方法或使用标志变量更清楚。早返回把非法输入挡在入口,避免多层 if;它不是“少写校验”,而是更早明确失败。

结构适合场景主要边界
if/else范围判断、组合条件、守卫条件嵌套太深时应提取命名条件或方法
switch 语句固定标签执行多条语句冒号写法要注意穿透和 break
switch 表达式把分类直接转换为一个值所有路径必须产值
for/增强 for次数、索引或遍历集合修改集合结构可能触发并发修改异常
while/do-while条件驱动或至少执行一次必须保证条件最终变化为假

常用用法 ​

if 与早返回:先处理非法输入 ​

早返回把边界条件挡在入口,减少嵌套;条件复杂时应提取有名字的方法。

java
// 输入:level 接收 score=80;只有 score 小于 0 或大于 100 时才会早返回 "invalid"。
public class GuardDemo {
    static String level(int score) {
    // 作用:早返回把边界条件挡在入口,减少嵌套;条件复杂时应提取有名字的方法。
        if (score < 0 || score > 100) {
            return "invalid";
        }
        return score >= 60 ? "pass" : "retry";
    }

    public static void main(String[] args) {
        System.out.println(level(80));
        // 输出:pass
    }
}

for:按次数或索引遍历 ​

循环初始化、条件和更新要共同推动状态变化,否则会出现死循环或越界。

java
public class ForDemo {
    public static void main(String[] args) {
        int total = 0;
        // 初始状态:total 当前为 0。
        for (int i = 1; i <= 3; i++) {
        // 作用:循环初始化、条件和更新要共同推动状态变化,否则会出现死循环或越界。
            total += i;
        }
        System.out.println(total);
        // 输出:6
    }
}

不常用但需要知道 ​

do-while:至少执行一次 ​

当业务要求先执行一次再判断时使用 do-while,否则优先使用更直观的 while。

java
// 初始状态:attempts 为 0;循环体先将它增加到 1,然后才检查 attempts < 1。
public class DoWhileDemo {
    public static void main(String[] args) {
        int attempts = 0;
        // 初始状态:attempts 当前为 0。
        do {
            attempts++;
        } while (attempts < 1);
        // 关键变化:while (attempts < 1) 在 attempts++ 把 attempts 从 0 变为 1 后判断为 false,do-while 因而恰好执行一次。
        System.out.println(attempts);
        // 输出:1
    }
}

标签循环:一次跳出多层循环 ​

标签适合极少数明确的多层跳出场景;多数时候提取方法或使用结果变量更易维护。

java
public class LabelLoopDemo {
    public static void main(String[] args) {
        int found = 0;
// 关键变化:found 接收表达式 0 的计算结果。
// 初始状态:found 的初始值为 0。
        search:
        for (int row = 0; row < 2; row++) {
            for (int column = 0; column < 2; column++) {
                found = row * 2 + column;
                break search;
            }
        }
        System.out.println(found);
        // 输出:0
    }
}

简单案例 ​

java
public class FlowDemo {
    static String classifyScore(int score) {
        if (score < 0 || score > 100) {
            return "invalid"; // 早返回:先挡住非法输入
        }
        return switch (score / 10) {
            case 10, 9 -> "A";
            case 8 -> "B";
            case 7 -> "C";
            default -> "D";
        };
    }

    public static void main(String[] args) {
        int score = 86;
        System.out.println(classifyScore(score));
        // 输出:B

        int total = 0;
        for (int value : new int[] {1, -2, 3, 0, 100}) {
            if (value < 0) {
                continue; // 跳过负数,继续下一轮
            }
            if (value == 0) {
                break;    // 遇到 0,结束最近一层循环
            }
            total += value;
        }
        System.out.println(total);
        // 输出:4

        int attempts = 0;
        while (attempts < 2) {
            attempts++;
        }
        int shown = 0;
        do {
            shown++;
        } while (shown < 1);
        System.out.println("loops=" + attempts + "," + shown);
        // 输出:loops=2,1
    }
}

classifyScore 先用早返回过滤非法分数,再用 switch 表达式得到等级。增强 for 依次读取数组元素,continue 忽略负数,break 在遇到 0 时结束;while 可能零次执行,而 do-while 保证至少执行一次。

易混点 ​

  • 传统 switch 是执行语句,switch 表达式必须产生值;箭头分支和冒号分支的穿透规则不同。
  • break 只结束最近一层循环或 switch,continue 只影响循环的当前轮次。
  • while 可能一次不执行,do-while 一定至少执行一次;不要只看条件文字判断次数。
  • for 的更新表达式不一定是 i++,但必须存在某种让循环走向终止的状态变化。
  • 早返回需要先校验输入再进入主路径;它不能代替对业务边界的明确说明。

课后小问 ​

  1. while (condition) 和 do { ... } while (condition) 的关键差异是什么? 答案:while 先判断条件,可能零次执行;do-while 先执行循环体,因此至少执行一次。 解析:读取菜单、重试一次输入等场景常要求先显示或先执行动作,此时 do-while 更直接;如果输入可能已经无效,先判断的 while 更安全。

  2. 为什么下面的 switch 可能同时打印两个结果? 答案:冒号分支没有 break 时会发生穿透,匹配一个 case 后继续执行后面的分支。 解析:可以在每个分支末尾加 break 或 return,也可以改用箭头分支;如果确实需要共享逻辑,应在注释中明确说明有意穿透。

  3. continue 和 break 都能跳过代码,它们的作用分别是什么? 答案:continue 跳过当前轮剩余代码并开始下一轮,break 直接结束最近一层循环。 解析:统计数据时可以用 continue 忽略不符合条件的项,但遇到结束标记时应使用 break;选错会导致漏算、死循环或多处理数据。

本节小结 ​

  • if 适合范围和组合条件,switch 适合离散标签,表达式版本还会直接产生分类结果。
  • for、增强 for、while 和 do-while 的差别主要在迭代来源与首次判断时机。
  • break 结束循环,continue 跳过当前轮,标签跳转低频且应谨慎使用。
  • 早返回把非法状态挡在入口,循环则必须有清楚的终止条件和状态变化。

快速回顾 ​

  • 能根据条件是范围还是离散标签选择 if 或 switch。
  • 能判断一个循环是否可能零次执行、是否至少执行一次以及是否会终止。
  • 能说明 break、continue 和早返回分别影响哪一层控制流。
  • 能读懂 switch 箭头分支和传统冒号分支的差异。

继续阅读 ​