java中string内存分配取决于创建方式:字面量存常量池(复用)、new在堆新建、intern可桥接两者;栈中只存引用,对象实体位于常量池或堆。

Java 中 String 对象的内存分配,关键看创建方式:字面量走常量池(复用),new 走堆(新建),intern 是两者的连接点。
双引号赋值:优先查常量池,复用已有实例
写 String s = "hello"; 时,JVM 在类加载阶段就把 "hello" 加入字符串常量池(JDK7+ 起位于堆内存中,逻辑仍称“常量池”)。后续相同字面量会直接复用该引用。
- 多个
String a = "abc"; String b = "abc";中,a == b为 true - 常量池中只存一份内容相同的字符串,节省内存
- 所有编译期确定的字符串字面量(如
"123"、"test")都进入常量池
new String(...):强制在堆中新建对象
执行 new String("hello") 时,JVM 一定在堆中分配新对象,哪怕常量池里已有 "hello"。
- 先确保常量池存在该字符串(若无则加入),再在堆中新建 String 实例
- 堆中对象的
value字段可能共享常量池里的字符数据,但对象本身地址唯一 -
String x = new String("abc"); String y = "abc";→x == y恒为 false - 每次 new 都产生新地址,由 GC 管理生命周期
intern():手动把堆对象登记进常量池
调用 .intern() 可将堆中字符串“映射”到常量池,返回池中引用。
-
new String("abc").intern() == "abc"结果恒为 true - 池中已存在相同内容 → 直接返回池中引用
- 池中不存在 → 把内容加入池,再返回新引用
- 适合动态拼接或外部输入后需复用的场景(如解析 JSON 字段名)
栈中只存引用,不存字符串实体
无论 String 对象在常量池还是堆中,变量(如 String s)本身是引用,始终存于栈帧的局部变量表。
- 栈中存的是地址,不是字符串内容
- 方法结束时,栈中引用自动消失;对象是否回收取决于是否还有其他引用
- 栈空间小、快、自动释放;真正影响内存行为的是对象实体所在位置(常量池 or 堆)
不复杂但容易忽略。核心就三点:字面量进池、new 进堆、intern 可桥接。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











