字符串常量池是JVM利用String不可变性实现的复用机制,关键在开发者正确使用:优先字面量、慎用new String()和intern(),JDK9+自动紧凑字符串优化内存。

字符串常量池本身不是“优化工具”,而是 JVM 利用 String 不可变性实现的复用机制。真正降低内存占用的关键,在于开发者对它的正确使用方式。
优先用双引号字面量,避免 new String()
编译期确定的字符串(如 "GET"、"SUCCESS")会自动进入常量池,后续相同字面量直接复用同一对象。
- ✅ 推荐:
String method = "POST";→ 复用池中对象,无额外堆分配 - ❌ 避免:
String method = new String("POST");→ 总在堆新建对象,即使内容重复也绕过池 - ⚠️ 注意:
"OK".intern()对字面量是冗余操作,因为已驻留,调用无意义
运行期高重复字符串可谨慎调用 intern()
从数据库、配置或网络读取的字符串,若内容高度重复且生命周期长(如状态码、币种、订单类型),适合显式归一化。
- 适用场景:
"PENDING"、"USD"、"Q4"等业务枚举类值 - 典型写法:
String status = rs.getString("status").intern(); - 效果示例:10 万条记录中 7 万个
"SUCCESS",经 intern 后仅保留 1 个实例,而非 7 万个堆对象
JDK 9+ 自动启用紧凑字符串,节省单字节字符内存
无需改代码,JVM 自动判断:当字符串只含 Latin-1 字符(ASCII 0–127,如英文、数字、常见符号),内部改用 byte[] 存储,每个字符占 1 字节,比旧版 char[](2 字节)节省约 50% 内存。
立即学习“Java免费学习笔记(深入)”;
- 完全透明:
length()、charAt()行为不变 - 生效条件:内容全为 ASCII 范围字符(例如
"user_id_123"✅,"用户"❌) - 验证方式:可用 JOL 工具查看实际内存布局
intern() 不是万能解,滥用反而伤性能
它是个全局同步操作,常量池在堆中(JDK 7+),锁竞争和 GC 压力真实存在。
- ? 禁止对唯一值调用:UUID、毫秒级时间戳、随机 token —— 几乎不重复,intern 后白占空间且难回收
- ? 避免循环内无条件调用:
for (...) { str.intern(); }→ 每次查哈希表+加锁,性能反降 - ? 更可控替代:对明确高频字段,用
ConcurrentHashMap<String, String>显式缓存,支持大小限制与淘汰策略


















