🐸 青蛙编程网
首页 / Java / Java 基础 / 4. 流程控制

流程控制

这是什么:流程控制 = 让程序做选择、重复干活的语法,主角是 if/switch 分支和 for/while 循环。

为什么用:到目前为止,程序都是「从上往下一条条执行」。可现实里总得判断「今天要不要带伞」,也得把 40 个成绩挨个加起来——没有分支和循环,你连批量处理数据都做不到。

如何用:本章先写 if/else 和 switch 做选择,再上 for、while 管重复,最后练嵌套循环和 break、continue。

if / else 和 switch:做选择

public class FlowDemo {
    public static void main(String[] args) {
        int score = 75;

        if (score >= 90) {
            System.out.println("优秀");
        } else if (score >= 60) {
            System.out.println("及格,继续加油");
        } else {
            System.out.println("挂科预警!");
        }

        int day = 6;
        switch (day) {
            case 6:
            case 7:                      // case 穿透:6 和 7 共用一段
                System.out.println("周末快乐!");
                break;
            default:
                System.out.println("工作日,搬砖");
                break;
        }
    }
}

输出:

及格,继续加油
周末快乐!

if 从上往下逐个检查条件,命中一个就进对应分支,后面的分支连看都不看;所有条件都不中,走 else 兜底。这决定了条件顺序很重要:上面代码如果把 score >= 60 放在 score >= 90 前面,75 分会被"及格"分支截胡,永远轮不到"优秀"——范围窄的条件放前面。

if 括号里放的是一个 boolean 表达式(值只能是 true 或 false),能用的比较和逻辑运算符一览:

运算符 含义 例子
== / != 等于 / 不等于 count == 0
> / < / >= / <= 大小比较 score >= 60
&& 并且(两边都真才真) age >= 18 && hasId
` ` 或者(一边真就真) day == 6 || day == 7
! 取反 !isVip

组合示例:

int age = 20;
boolean hasTicket = true;
if (age >= 18 && hasTicket) {
    System.out.println("检票通过,请入场");
} else {
    System.out.println("无法入场");
}

输出:

检票通过,请入场

switch 适合"固定几个选项多选一"。它的执行方式要特别注意:命中一个 case 后,程序会从那里一路往下执行,直到撞见 break 才停——这叫 case 穿透。利用穿透可以让多个选项共用一段代码(6 和 7 都是周末),但漏写 break 是新手经典坑,本页下方翻车现场有它的事故报告。JDK 14+ 还有箭头写法 case 6 ->,能不用写 break,见到能认出即可。

if 还是 switch?给出选择依据:

场景 选谁 原因
条件是范围(大于、小于、区间) if switch 只能匹配具体值,做不了范围
条件是组合逻辑(并且/或者) if && ` ` 更直观
一个变量匹配固定几个值 switch case 一列,选项一目了然

for、while、do-while:重复干活

public class LoopDemo {
    public static void main(String[] args) {
        // for:知道要循环几次时用
        for (int i = 1; i <= 3; i++) {
            System.out.println("第 " + i + " 次俯卧撑");
        }

        // while:满足条件就一直做
        int water = 3;
        while (water > 0) {
            System.out.println("喝一口水,剩 " + water);
            water--;
        }

        // do-while:先干一次,再问"还继续吗"
        int count = 0;
        do {
            count++;
        } while (count < 0);   // 条件一开始就不满足,但也执行了 1 次
        System.out.println("do-while 执行了 " + count + " 次");
    }
}

输出:

第 1 次俯卧撑
第 2 次俯卧撑
第 3 次俯卧撑
喝一口水,剩 3
喝一口水,剩 2
喝一口水,剩 1
do-while 执行了 1 次

把 for 的结构拆开看,括号里是三段式,用分号隔开:

部分 例子 执行时机
初始化 int i = 1 进循环前执行一次
条件 i <= 3 每轮开始前检查,不满足就退出
更新 i++ 每轮结尾执行,推动循环靠近终点

i++ 是"自增 1"的简写,等价于 i = i + 1;对应还有 i-- 自减。for 循环的变量 i 只活在循环里——出了那对大括号它就消失了(这叫作用域,方法章还会细讲)。

三种循环的本质区别只有一个:条件检查的时机。for 和 while 是"先检查再干活",一次都可能不干;do-while 是"先干活再检查",保底干一次。日常写代码,for 和 while 覆盖绝大多数场景。

语法 什么时候用
for 循环次数明确(如"跑 10 遍")
while 只知道条件,不知道几轮(如"水没喝完就继续")
do-while 至少干一次,再判断继不继续
switch 固定几个选项多选一

嵌套循环:循环里套循环

循环体内还可以再放循环,外层转一圈,内层转一整圈——经典的九九乘法表:

public class NineTable {
    public static void main(String[] args) {
        for (int i = 1; i <= 3; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print(j + "×" + i + "=" + (i * j) + "\t");
            }
            System.out.println();   // 内层打完一行,换行
        }
    }
}

输出:

1×1=1
1×2=2   2×2=4
1×3=3   2×3=6   3×3=9

读这段代码的诀窍:外层 i 管"第几行",内层 j 管"这一行打几项"。i 是 1 时 j 转一轮,i 是 2 时 j 转两轮……注意这里用了 print(不换行)和 println(换行)的组合拳,\t 是制表符,负责对齐。把 i <= 3 改成 i <= 9,完整的九九乘法表就出来了。

嵌套循环的总执行次数是内外圈数的乘积:外层 9 次 × 内层最多 9 次 ≈ 81 次内层循环。嵌套超过三层通常意味着代码该拆了,这是后话。

break 和 continue:循环的遥控器

  • break:整个循环立刻结束,"不干了,走人"
  • continue:跳过本轮剩余代码,直接进入下一轮,"这句跳过,继续"
public class BreakDemo {
    public static void main(String[] args) {
        for (int i = 1; i <= 5; i++) {
            if (i == 3) {
                continue;   // 跳过 3
            }
            if (i == 5) {
                break;      // 到 5 直接收工
            }
            System.out.println("处理第 " + i + " 件");
        }
        System.out.println("循环结束");
    }
}

输出:

处理第 1 件
处理第 2 件
处理第 4 件
循环结束

i 等于 3 时 continue 让"打印"被跳过;i 等于 5 时 break 让整个循环戛然而止。这两招在"遍历中寻找、遍历中过滤"的场景天天用:找到目标就 break,不合规的就 continue。

大括号惯例

Java 社区的铁规矩:哪怕里面只有一行,也写上大括号 {}。省大括号一时爽,回头加代码直接埋 bug。

// 危险写法:看起来加了一行,实际只有第一行受 if 管
if (isVIP)
    System.out.println("欢迎贵宾");
    System.out.println("赠送优惠券");   // ❌ 无论是不是 VIP 都会执行!

大括号圈定了"哪些行受 if 管辖"。没有大括号时,if 只管紧跟的那一句。上面第二行缩进得再乖巧,语法上它已经跳出 if 的管辖,无条件执行——缩进骗得了人眼,骗不了编译器。

❓ 常见问题

Q1:&& 和 & 有什么区别?

日常写 && 就对了。&& 有"短路"能力:左边已经能定生死时,右边根本不执行。比如 age != 0 && 10 / age > 1,当 age 是 0 时左边为假,右边的除法不会执行,避免了除零错误。单个 & 没有这个保护,两边都会算。

Q2:while 循环停不下来怎么办?

八成是死循环——条件永远为真,或忘了在循环体内更新条件变量(比如忘了 water--)。命令行里按 Ctrl + C 强制终止程序。写 while 时先自问一句:"什么变量在变化?它如何推动条件走向不成立?"

Q3:if 判断两个字符串相等能用 == 吗?

不能,这是 Java 名坑:== 比的是"是不是同一个对象"而不是内容,比字符串内容必须用 equals。原理在字符串章血泪警告一节讲透,这里先埋个种子。

Q4:循环变量为什么习惯叫 i、j?

index(索引)的传统缩写,从数学求和符号沿用至今,全世界的程序员都认。真正的业务代码里,能起有意义的名字就起(如 score、index),纯计数的循环用 i/j/k 完全没问题。

⚠️ 新手翻车现场

翻车一:switch 漏写 break

int day = 6;
switch (day) {
    case 6:
        System.out.println("周六");
    case 7:
        System.out.println("周日");
        break;
}

完整输出:

周六
周日

问题:本想只打印"周六",但 case 6 没有 break,穿透到了 case 7 的代码,多打了一行。穿透不报错,属于"程序活着但结果不对"的暗伤,最难查。

修正:每个 case 的代码结尾都补 break;,除非你刻意利用穿透共享代码。

翻车二:if 条件里写赋值

int score = 60;
if (score = 100) {   // ❌ 编译报错
    System.out.println("满分!");
}

完整报错:

错误: 不兼容的类型: int无法转换为boolean

问题:= 是赋值,== 才是比较。在 C/JS 里这是悄悄生效的坑,好在 Java 的 if 括号里必须是 boolean,int 塞进去直接编译报错——强类型又一次救了你。

修正:比较相等一律写两个等号 score == 100。

翻车三:for 括号后多打了一个分号

for (int i = 0; i < 3; i++);
{
    System.out.println("跑了 " + i + " 圈");   // ❌ 报错:找不到 i
}

问题:for (...) 后面那个分号让循环体变成了"空语句"——循环空转三轮,下面的大括号块和 for 已经无关,还因为出了 i 的作用域而报错。一个分号,双重暴击。

修正:删掉 for 括号后的分号。这个坑的变体(if 后多分号)同理。

翻车四:while 忘了更新条件

int water = 3;
while (water > 0) {
    System.out.println("喝水");   // ❌ 没人让 water 减小,死循环
}

问题:条件 water > 0 永远成立,程序陷入死循环,风扇起飞。

修正:循环体里补 water--;。记住口诀:while 循环体内,必须有变量朝"条件不成立"的方向变化。

🎯 什么时候用什么结构

需求 首选结构
成绩分档、多条件组合判断 if / else if / else
菜单选项、星期几等固定值分发 switch
已知次数的重复(打 10 行、遍历数组) for
满足条件才继续(用户没输对就重问) while
至少执行一次(先展示菜单再问要不要继续) do-while
遍历中提前退出 / 跳过某些项 循环 + break / continue

📝 本章小结

  • if / else if / else 自上而下检查,命中即停;范围窄的条件放前面
  • switch 命中后一路穿透直到 break;固定值多选一用它,范围判断用 if
  • for 三段式(初始化;条件;更新),次数明确用它;while 只看条件;do-while 保底一次
  • break 结束整个循环,continue 跳过本轮
  • 无论多短,分支和循环体都写大括号;if 括号里必须是 boolean,比较用 ==
  • 记忆口诀:次数明确用 for,条件不明用 while,先斩后奏 do-while,多选一找 switch,break 记得带。

记忆锚点:程序是一本"选择冒险"游戏书——if 是岔路口(选一条路走),switch 是菜单点菜(只上一个菜),for 是"绕操场跑 10 圈"(圈数已知),while 是"跑到没水喝为止"(条件说了算),break 是中途退赛,continue 是这一圈偷个懒。

动手改

  1. 把 score 改成 59、60、90 分别跑一遍,验证分支走向
  2. 用 for 循环打印 1~100 里所有的偶数(提示:i % 2 == 0)
  3. 写一个 while 循环,从 5 倒数打印到 1
  4. 把九九乘法表的外层改成 i <= 9,跑出完整表格
  5. 写一个 for 循环打印 1~20,遇到 7 的倍数用 continue 跳过、遇到 15 用 break 收工,先纸上推演再运行验证

下一章:数组,一次管理一批数据 🐸

📥 下载本章代码

ZIP 内含本章全部代码文件与说明,解压即用,与教程内容同步生成。