一、简明教程:Switch Case 穿透原理与避坑
在编程中,
switch-case语句非常常用。但初学者经常会遇到一个经典的坑:Case 穿透(Fall-through)。今天我们用最简单的代码把它说清楚。
1. 什么是 Case 穿透?
在 switch 语句中,当程序成功匹配到一个 case 后,如果没有遇到 break; 语句,程序不会退出 switch,而是无视后面所有的判断条件,直接执行下面所有 case 的代码。
2. 为什么会穿透?(底层原理)
底层编译时,switch-case 不是在做逻辑判断,而是在生成跳转标签(入口)。
匹配成功 = 找到入口:程序直接跳转到那个入口开始执行。
顺序执行:一旦进去了,CPU 就只会顺着代码往下跑,它不知道各个
case之间的界限在哪。遇到
break停止:break就像一堵墙。只有碰到它,程序才会强制跳出switch。没有墙,就一直往下冲。
3. 代码演示
我们来看 Java 代码中最典型的反面教材和正面教材。
❌ 错误示范:忘记写 break 导致Bug
int day = 2;
switch (day) {
case 1:
System.out.println("星期一");
case 2:
System.out.println("星期二"); // 匹配成功,从这里进入!
case 3:
System.out.println("星期三"); // 💥没有break,发生穿透,依然执行!
default:
System.out.println("未知"); // 💥继续穿透!
}
输出结果:
星期二
星期三
未知
✅ 正确示范:利用穿透简化代码
穿透不是Bug,是个特性。如果多个条件要执行相同的代码,我们可以故意省略 break。
int month = 4;
String season = "";
switch (month) {
case 3:
case 4: // 匹配4,但没有break
case 5: // 穿透到5
season = "春季"; // 3,4,5月统一在这里处理
break; // 遇到break,完美跳出
case 6:
case 7:
case 8:
season = "夏季";
break;
default:
season = "其他";
}
System.out.println(season); // 输出: 春季
4. 最佳实践建议
时刻警惕:写完
case下意识检查有没有写break。留下注释:如果你是故意利用穿透(如上面的案例),强烈建议在空
case旁边写上注释// fall through,防止同事复盘时当成Bug给你“修复”了。拥抱新语法:如果你使用 Java 14+,推荐使用新的箭头语法
->,它天生自带break效果,再也不用担心穿透问题。
// Java 14+ 新语法
String season = switch (month) {
case 3, 4, 5 -> "春季";
case 6, 7, 8 -> "夏季";
default -> "其他";
};
二、什么时候用for,什么时候用while?
功能上是完全一样的,for能解决的while也能解决,反之亦然。
使用规范:知道循环几次:使用for;不知道循环几次建议使用:while。
for循环中,控制循环的变量只在循环中使用。while循环中,控制循环的变量在循环后还可以继续使用。

三、Java 生成随机数的 3 种常见姿势
在日常开发中,生成随机数是一个非常常见的需求:无论是抽奖逻辑、生成验证码,还是测试数据的模拟。今天我们就来盘点一下 Java 中生成随机数最常用的 3 种方式。
1. 最简单的入门级:Math.random()
Math.random() 是大家最熟悉的 API。它会返回一个 [0.0, 1.0) 之间的 double 类型伪随机数(包含 0.0,不包含 1.0)。
使用场景:简单的、对性能要求不高的单机小脚本。
// 生成一个 0 到 100 之间的随机整数(包含0,不包含100)
int randomInt = (int) (Math.random() * 100);
System.out.println("Math.random() 生成的随机数: " + randomInt);
2. 经典的万金油:java.util.Random
如果你需要更丰富的随机类型(比如直接生成 int、boolean),java.util.Random 是标准答案。
使用场景:大多数普通的单线程业务逻辑。
import java.util.Random;
Random random = new Random();
// 1. 生成任意范围的 int
int anyInt = random.nextInt();
// 2. 生成 0 到 100 之间的随机整数(包含0,不包含100)
int rangeInt = random.nextInt(100);
System.out.println("Random 生成的 0-100 随机数: " + rangeInt);
3. 高并发场景王者:ThreadLocalRandom
在多线程环境下,多个线程共享同一个 Random 实例会导致底层竞争,从而严重降低性能。Java 7 引入了 ThreadLocalRandom,它为每个线程维护独立的种子,完美解决了并发冲突。
使用场景:多线程环境、高并发系统(如 Web 服务端核心业务)。
import java.util.concurrent.ThreadLocalRandom;
// 生成 10 到 50 之间的随机整数(包含10,不包含50)
// 注意:用法是 ThreadLocalRandom.current().nextInt(origin, bound)
int concurrentInt = ThreadLocalRandom.current().nextInt(10, 50);
System.out.println("ThreadLocalRandom 生成的 10-50 随机数: " + concurrentInt);
总结与建议
-
平时做小练习:直接用
Math.random(),图个方便。 -
常规的单线程项目:使用
java.util.Random,API 很丰富。 -
多线程/高并发项目:别犹豫,无脑上
ThreadLocalRandom,不仅性能强而且绝对线程安全。