
用 Random 生成固定长度随机字符串的可靠写法
别直接拼接 Math.random() 或循环调用 nextInt() 然后强转 char——容易越界或生成控制字符。Random 本身不负责字符映射,得自己限定合法字符集范围。
推荐做法:预定义一个合法字符数组(比如大小写字母 + 数字),用 random.nextInt(charArray.length) 当下标取值。这样既避免非法 Unicode、又保证分布均匀。
-
Random实例建议复用,不要每次生成都 new 一个(影响性能,还可能因快速重复创建导致种子相近) - 字符数组长度最好选质数(如 62),减少模运算周期性偏差(虽对一般业务影响极小,但知道有这回事)
- 如果需要线程安全,改用
ThreadLocalRandom.current(),它比共享Random实例更轻量
char[] chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray(); Random rnd = new Random(); StringBuilder sb = new StringBuilder(10); for (int i = 0; i <h3>为什么不用 <code>UUID.randomUUID().toString()</code> 替代</h3> <p>它确实“随机”,但输出是 32 位十六进制 + 4 个短横线(共 36 字符),格式固定、长度不可控、含非字母数字字符。如果你要的是 8 位纯字母数字验证码,<code>UUID</code> 就是杀鸡用牛刀,还多出一堆连字符和大小写混杂的冗余信息。</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5703" title="deep-java-review"><img src="https://img.php.cn/upload/skill/000/000/081/179060057413304.jpg" alt="deep-java-review" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill5703" title="deep-java-review" class="overflowclass">deep-java-review</a> <p class="overflowclass">Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...</p> </div> <a rel="nofollow" href="/xiazai/skill5703" title="deep-java-review" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>
- 生成开销略大(涉及 SecureRandom、MAC 地址/时间戳等组合)
- 不能指定字符集(比如只要大写字母,或排除易混淆字符 O/0、l/1)
- 去横线再截断容易误切——
uuid.toString().replace("-", "").substring(0, 8)看似简单,实则破坏了随机性(前缀截断偏向某些哈希段)
避免 Random.nextInt(int bound) 越界或死循环
常见错误是把字符集长度硬编码成 magic number,比如 rnd.nextInt(62),但实际字符数组只有 61 个元素——运行时抛 IllegalArgumentException: bound must be positive 或静默出错(如果 bound=0)。
- 永远用
chars.length作为nextInt()的参数,而不是手敲数字 - 确保
chars非空,否则length == 0会触发异常;可加一行if (chars.length == 0) throw new IllegalArgumentException("char array must not be empty"); - 不要用
(char) rnd.nextInt(26 + 26 + 10)这类强制类型转换——ASCII 码不连续,'A'到'Z'是 26 个,但'Z'+1是'[',不是'a'
需要密码级安全性时,必须换 SecureRandom
普通 Random 是伪随机,基于线性同余,可被预测。如果是生成重置令牌、API 密钥这类敏感字符串,Random 不够用。
- 替换构造方式:
new SecureRandom(),其余逻辑完全一致(它也支持nextInt(bound)) - 注意首次调用可能稍慢(要采集系统熵),但后续很快;若在高并发场景下频繁 new,考虑复用实例
- 别试图用
SecureRandom去“增强”Random(比如拿它生成 seed 再喂给 Random)——没意义,反而绕过安全机制
真正难的不是写几行代码,而是想清楚这个字符串用在哪:是前端展示的临时 ID,还是后端签发的访问凭证?前者用 Random 足够,后者漏掉 SecureRandom 就等于把钥匙挂门把手上。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










