String.intern()将字符串“尝试”加入常量池并返回池中引用:若存在则直接返回,否则加入后返回;JDK 7+常量池在堆中,存的是对象引用;常用于运行时字符串复用或==比较,但需防常量池膨胀。

Java 中 String.intern() 方法的作用,是将一个字符串对象“尝试”加入字符串常量池,并返回常量池中对应字符串的引用。
intern 的核心逻辑
调用 intern() 时,JVM 会检查字符串常量池中是否已存在一个内容完全相同的字符串(通过 equals() 判断):
- 如果存在,直接返回常量池中该字符串的引用;
- 如果不存在,就把当前字符串对象的引用(注意:不是复制内容,而是引用本身)放入常量池,并返回这个引用(JDK 7+ 后,常量池在堆内存中,所以放的是堆中对象的引用)。
手动放入常量池的典型场景
最常见的是对运行时创建的字符串(如拼接、new String() 构造)显式调用 intern(),使其进入常量池,从而复用或用于 == 比较:
-
String s1 = new String("hello");→ 此时s1指向堆中新对象,常量池已有 "hello"(字面量),但s1本身没进池; -
String s2 = s1.intern();→ 检查到常量池已有 "hello",返回池中那个引用,所以s2 == "hello"为 true; - 若字符串内容在常量池中原本不存在(比如动态拼接结果),
intern()会把它加入池中,后续再调用可复用。
注意事项和常见误区
不要误以为 intern() 总是“复制一份放进去”,也不代表原对象被修改:
立即学习“Java免费学习笔记(深入)”;
-
intern()返回的是常量池中的引用,与原对象是否相同取决于池中是否存在; -
new String("abc").intern() == "abc"是 true(因为字面量 "abc" 已在池中); -
new String("def").intern() == new String("def").intern()也是 true(两次都返回池中唯一引用); - 频繁调用
intern()可能引发常量池膨胀(尤其 JDK 6 常量池在永久代,容易 OOM),JDK 7+ 放在堆里缓解了该问题,但仍需谨慎。
简单验证方式
可通过 == 比较和 System.identityHashCode() 辅助判断是否指向同一对象:
String a = "test";String b = new String("test").intern();System.out.println(a == b); // trueSystem.out.println(System.identityHashCode(a) == System.identityHashCode(b)); // true


















