Java 分支循环与流程控制
更新时间:2026-09-21。运算符的短路与类型提升见 运算符与表达式,本篇把分支、循环、跳转里最容易写错的点一次讲清。
一、if/else 的两个坑
悬空 else:else 永远配对最近的未配对 if,与缩进无关。
if (a > 0)
if (b > 0) System.out.println("AB");
else System.out.println("?"); // 它配对的是内层 if,不是外层!想让 else 配外层必须用花括号。一律加 {} 是最省事的纪律,哪怕只有一条语句。
布尔条件不能像 C 那样写整数:if (x = 1) 编译不过(赋值表达式是 int,不能当 boolean),这反而避免了 C 里把 == 误写成 = 的经典 bug。
二、switch:支持的类型与穿透
传统 switch 只接受 byte/short/int/char、其包装类、枚举与 String(JDK7+),不支持 long/float/double/boolean。
最大的坑是 case 穿透(fall-through):没有 break 会一路执行后面的 case。
switch (day) {
case 1: case 2: case 3:
System.out.println("周初"); // 1/2/3 都落到这里:故意穿透,合法
break;
default:
System.out.println("其他");
}故意穿透要写注释说明;IDE/SpotBugs 会对「case 里有语句却没 break」报警。
三、JDK14+ switch 表达式(推荐)
箭头 -> 不穿透、可返回值,多值用逗号;需要整块代码时用 yield 返回:
int len = switch (s) {
case "a", "b" -> 1;
case "abc" -> 3;
default -> {
System.out.println("计算中");
yield s.length(); // 块里用 yield 返回
}
};switch 表达式要求穷举:要么有 default,要么对枚举每个常量都给分支,否则编译错误,比传统 switch 漏 case 更安全。
四、三种循环怎么选
| 循环 | 适用 | 备注 |
|---|---|---|
for | 已知次数、需要索引 | 三部分都可空,for(;;) 即死循环 |
while | 先判断、次数不定 | 可能一次不执行 |
do-while | 至少执行一次 | 末尾分号别漏 |
增强 for | 只顺序读数组/Iterable | 拿不到索引、不能删元素 |
增强 for 遍历集合时删除元素会抛 ConcurrentModificationException,要删用 Iterator.remove() 或 removeIf:
list.removeIf(x -> x < 0); // 推荐
for (Iterator<Integer> it = list.iterator(); it.hasNext();)
if (it.next() < 0) it.remove(); // 唯一安全的边遍历边删五、break / continue 与标签
break跳出当前循环;continue跳过本轮剩余语句进入下一轮。- 嵌套循环想一次跳出外层用标签(Java 不 goto,但保留带标签的 break/continue):
outer:
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (i * j == 4) break outer; // 直接跳出双层循环标签少用为妙,通常抽成方法 + return 更清晰。
六、常见坑
- 用 double/float 当循环变量:
0.1无法精确表示,累加次数可能不符预期;计数用整数。 - 循环条件写错方向:
for (int i=0; i>n; i++)一次都不进。 - 在增强 for 里改结构:用 removeIf 或 Iterator。
- switch 漏 break:排查「为什么后面分支也执行」先看穿透。
- switch 用了 long/float:编译错误,先转成支持的类型。
总结
if/else 一律加花括号避开悬空 else,条件必须是 boolean;传统 switch 仅支持 int 系/char/枚举/String,最大的坑是漏 break 导致穿透,JDK14 起优先用箭头 switch 表达式(不穿透、可返回值、块内 yield 且要求穷举);已知次数用 for、条件不定用 while、顺序只读用增强 for,边遍历边删必须 Iterator.remove 或 removeIf,break/continue 只管当前循环、跳多层才用标签,循环计数变量别用浮点。