String Constant Pool(字符串常量池)
一、核心概念(通俗解释)
可以把字符串常量池理解成一个「字符串缓存池」:
- 当你创建字符串(比如
String s = "hello")时,JVM 会先去常量池里找有没有内容为"hello"的字符串。 - 如果有,直接返回这个字符串的引用(相当于「复用」);如果没有,就先在常量池里创建
"hello",再返回引用。 - 而通过
new String("hello")创建的字符串,会在 堆内存 新建对象,同时常量池里也会创建"hello"(如果之前没有),这也是为什么new String会比直接赋值多占用内存。
二、代码示例:直观理解常量池机制
java
运行
public class StringConstantPoolDemo {
public static void main(String[] args) {
// 方式1:直接赋值,字符串存入常量池,复用已有对象
String s1 = "hello";
String s2 = "hello";
// 方式2:new 创建,堆内存新建对象,常量池仍会存"hello"(若不存在)
String s3 = new String("hello");
String s4 = new String("hello");
// 对比引用(== 比较对象地址,equals 比较内容)
System.out.println(s1 == s2); // true:s1和s2指向常量池同一个"hello"
System.out.println(s1 == s3); // false:s1指向常量池,s3指向堆内存对象
System.out.println(s3 == s4); // false:s3和s4是堆里两个不同对象
System.out.println(s1.equals(s3)); // true:内容相同
// intern() 方法:将堆中的字符串对象"入池",返回常量池引用
String s5 = s3.intern();
System.out.println(s1 == s5); // true:s5现在指向常量池的"hello"
}
}
三、关键知识点
-
存储位置:
- JDK 1.6 及之前:常量池位于 方法区(永久代);
- JDK 1.7 及之后:常量池被移到 堆内存(更灵活,避免永久代内存溢出)。
-
核心方法:intern ()
- 作用:将当前字符串对象的内容存入常量池(若不存在),并返回常量池中的引用;
- 场景:当需要复用动态生成的字符串(比如拼接后的字符串)时,用
intern()可优化内存。
-
字符串拼接的特殊情况:java运行
String s1 = "a" + "b"; // 编译期优化,直接等同于"ab",存入常量池 String s2 = "ab"; System.out.println(s1 == s2); // true String a = "a"; String b = "b"; String s3 = a + b; // 运行期拼接,会new String("ab"),存在堆中 System.out.println(s3 == s2); // false System.out.println(s3.intern() == s2); // true
四、实际应用价值
- 内存优化:避免大量重复字符串占用内存(比如业务中频繁使用的固定字符串,如 "success"、"fail");
- 性能提升:复用已有对象减少 GC(垃圾回收)压力,字符串比较时
==比equals更快(但仅适用于常量池字符串)。
总结
- 字符串常量池是 JVM 优化字符串内存的缓存机制,直接赋值的字符串会优先存入常量池并复用;
new String()会在堆创建新对象,可通过intern()方法将内容入池复用;- JDK 1.7 后常量池移至堆内存,拼接字符串的编译期 / 运行期处理逻辑不同,需注意引用对比的差异。

浙公网安备 33010602011771号