String不可变性是其内存与性能优化的核心:对象内容锁死,所有“修改”均返回新实例;常量池复用、哈希缓存、线程安全及JDK9+紧凑字符串(byte[]+coder)降内存均由此支撑。

Java 中 String 的内存管理与性能优化,核心在于理解它的不可变性、常量池机制、内部存储演进,以及不同操作带来的实际开销。用错方式,一行拼接就可能拖慢整个服务;用对了,内存减半、GC 减少、响应更快。
字符串创建:字面量优先,new 要谨慎
双引号创建的字符串字面量(如 "user_id")会自动进入字符串常量池,重复声明直接复用引用,不产生新对象。
-
推荐写法:
String key = "status";—— 安全、轻量、线程共享 -
避免写法:
String key = new String("status");—— 总是在堆新建对象,即使常量池已有相同内容 - 例外情况:只有当你明确需要一个独立于常量池的副本(比如做敏感字段隔离),才考虑
new String(...),但极少见
字符串拼接:别在循环里用 +,StringBuilder 是主力
每次用 += 或 + 拼接,都会生成新的 String 对象。循环 10000 次,就创建 10000 个临时对象,大量进入老年代,触发频繁 GC。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 单条语句拼接(如
"a" + "b" + "c")由编译器优化为常量,没问题 - 变量参与拼接(尤其在 for/while 中)必须改用
StringBuilder - 初始化时预估容量:
new StringBuilder(256)比默认 16 更稳,避免多次数组扩容复制 - 拼完务必调
toString()获取结果,否则传的是 StringBuilder 实例,运行时报错
字符串常量池:intern() 不是银弹,得看场景
从 JDK 7 起,常量池移到堆中,可被 GC 回收;JDK 8+ 依然在堆,不是元空间。这意味着 intern() 的行为更可控,但也更需谨慎。
立即学习“Java免费学习笔记(深入)”;
-
适合 intern:长期存活、高重复率、作 Map 键或配置项名,例如
"HTTP_404"、"redis.host" - 不适合 intern:用户输入、日志消息、临时路径、循环内生成的短生命周期字符串
- 调用
intern()后返回的是常量池引用,原对象仍存在,只是多一条链路 - 验证是否成功:用
==判断引用相等,.equals()判断内容相等
底层存储:JDK 9+ 的紧凑字符串真省内存
Java 9 引入 byte[] + coder 机制,让只含 ASCII 或 Latin-1 字符的字符串(如数字 ID、状态码、英文字段名)内存占用直接减半——每个字符从 2 字节降到 1 字节。
- coder = 0 → Latin-1 编码(单字节),适用于大多数配置键、协议标识、数字串
- coder = 1 → UTF-16 编码(双字节),用于含中文、emoji、特殊符号的字符串
- 这个判断全自动,开发者无需干预,但了解它有助于解释为什么同样长度的字符串,内存差异可能很大
- substring、indexOf 等方法内部会根据 coder 分支处理,性能影响已大幅收敛


















