Java 流程控制
Java 的条件、循环与分支:if/switch、for/while、break/continue 如何组织结构化控制流。
#concept
#growing
#dev
#java
[!info] related notes
Java 流程控制
这个概念为什么出现
业务规则是分支与循环的组合:库存够不够、状态机如何跳转、批处理如何扫单。Java 提供结构化控制流,避免回到随意 goto 风格。
[!abstract] 一句话理解 用
if/else、switch、for/while/do-while与break/continue组织分支与迭代;if/循环条件须为 boolean 或可拆箱的 Boolean;没有 C 式整数真值转换。
最小可运行示例
先把示例放进业务场景,再看代码:
场景:批处理任务按订单状态分流并跳过已取消单
扫描订单数组:取消跳过,待支付计数,已支付累加金额。
教学点:for-each、if、continue、switch。
public class OrderBatch {
enum Status { CREATED, PAID, CANCELLED }
static final class Order {
final String id;
final Status status;
final int amountCents;
Order(String id, Status status, int amountCents) {
this.id = id;
this.status = status;
this.amountCents = amountCents;
}
}
// summarize:生成批处理摘要。
//
// 业务意图:一遍扫描得到待支付数量与已支付总额。
// 教学点:continue 跳过取消单;switch 按状态分流。
static void summarize(Order[] orders) {
int pending = 0;
long paidSum = 0; // 避免多个 int 金额累加时发生 int 溢出
for (Order o : orders) {
if (o.status == Status.CANCELLED) {
// 取消单不进入后续统计。
continue;
}
switch (o.status) {
case CREATED -> pending++;
case PAID -> paidSum += o.amountCents;
default -> throw new IllegalStateException("unhandled status: " + o.status);
}
}
System.out.println("pending=" + pending + " paidSum=" + paidSum);
}
public static void main(String[] args) {
Order[] orders = {
new Order("1", Status.CREATED, 100),
new Order("2", Status.PAID, 200),
new Order("3", Status.CANCELLED, 300),
new Order("4", Status.PAID, 50)
};
summarize(orders);
}
}
建议运行:
javac OrderBatch.java && java OrderBatch
期望输出:
pending=1 paidSum=250
结合场景再看三个关注点
- 条件须为 boolean 或可拆箱的 Boolean:
if (stock)对 int 不成立,Boolean 为 null 时会拆箱失败。 - 本例的 default 显式失败,不会静默忽略新状态;空 default 没有防漏作用。完整枚举 switch 表达式也可不写 default,让重新编译时检查穷尽性。
continue/break降低嵌套,但过深循环应拆方法。
核心概念与准确模型
1. if / else
- 条件类型可为 boolean 或 Boolean;后者会拆箱,null 会抛 NPE。
else if按顺序选择第一个成立分支;先保证业务优先级正确,只有重排不改变语义时才考虑成本。
2. switch
- switch 表达式与箭头标签在 Java 14 正式提供;箭头也可用于 switch 语句,不能只凭
->判断它是表达式。Java 21 正式支持模式 switch。 - 对枚举与字符串切换很实用
- 注意
break贯穿(传统冒号语法)问题;箭头形态避免贯穿
3. 循环
| 形态 | 适合 |
|---|---|
for | 已知次数/索引扫描 |
| 增强 for | 遍历数组/Iterable |
while | 条件驱动 |
do-while | 至少一次 |
4. break / continue / 标签
break结束循环或 switchcontinue进入下一次迭代步骤:普通 for 先执行更新表达式,while/do-while 则检查相应循环条件。- 标签 break 可跳出多层——可读性成本高,优先重构
边界情况与反直觉行为
- 增强 for 没有统一的“禁止修改”规则:可修改数组元素或可变对象;集合结构修改是否允许及如何检测取决于其迭代契约,见集合篇。
- 浮点当循环条件易死循环或误差。
- 空数组 for-each 安全,零次迭代。
常见误区
[!warning] 常见误区:switch 忘记 break 传统冒号语法会贯穿到下一 case。箭头标签
->更不易踩坑。
工程实践
- 复杂分支用多态或策略表替代巨型 switch(OOP 阶段再深化)。
- 循环体内避免重复计算不变式。
- 批处理记录“处理/跳过/失败”计数,便于对账。
本节总结
- 结构化分支与循环是业务规则骨架
- boolean 条件、枚举 switch、增强 for 是日常主力
- 版本带来的 switch 表达式应查当前 JDK 文档
自测题
- 为什么
if (1)在 Java 非法? - 批处理中
continue与把条件嵌套在大if里如何取舍?
参考答案
- 条件只能是 boolean 或可拆箱的 Boolean,整数 1 不会隐式转为布尔值。
- 早继续可降低嵌套、突出主路径;但过多 continue 也要拆方法保持清晰。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| JLS Statements | 规范 | 语句与控制流 |