程序流程控制

一、简明教程:Switch Case 穿透原理与避坑

在编程中,switch-case 语句非常常用。但初学者经常会遇到一个经典的坑:Case 穿透(Fall-through)。今天我们用最简单的代码把它说清楚。

1. 什么是 Case 穿透?

switch 语句中,当程序成功匹配到一个 case 后,如果没有遇到 break; 语句,程序不会退出 switch,而是无视后面所有的判断条件,直接执行下面所有 case 的代码

2. 为什么会穿透?(底层原理)

底层编译时,switch-case 不是在做逻辑判断,而是在生成跳转标签(入口)

  1. 匹配成功 = 找到入口:程序直接跳转到那个入口开始执行。

  2. 顺序执行:一旦进去了,CPU 就只会顺着代码往下跑,它不知道各个 case 之间的界限在哪。

  3. 遇到 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. 最佳实践建议

  1. 时刻警惕:写完 case 下意识检查有没有写 break

  2. 留下注释:如果你是故意利用穿透(如上面的案例),强烈建议在空 case 旁边写上注释 // fall through,防止同事复盘时当成Bug给你“修复”了。

  3. 拥抱新语法:如果你使用 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循环中,控制循环的变量在循环后还可以继续使用。

image.png

三、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

如果你需要更丰富的随机类型(比如直接生成 intboolean),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,不仅性能强而且绝对线程安全。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容