string.intern()用于将字符串手动加入常量池:若池中已存在相同内容字符串,则返回其引用;否则将当前字符串引用加入池中并返回(jdk7+直接存堆对象引用),从而实现内存复用和==高效比较。

String.intern() 是 Java 中将字符串对象手动加入字符串常量池(String Pool)的方法。它不会“创建”新常量,而是检查常量池中是否已存在相同内容的字符串;若存在,直接返回池中引用;若不存在,则将当前字符串(或其副本)放入池中,并返回该引用。
intern() 的核心行为
调用 intern() 时:
- JVM 会按字符序列(Unicode 码点)逐个比对常量池中已有的字符串内容
- 只要内容完全相等(
equals()为 true),就复用已有引用 - 如果未命中,JVM 会把该字符串对象的引用(不是拷贝)存入常量池(JDK 7+ 后,常量池在堆内存中)
- 方法始终返回常量池中的那个引用,类型仍是
String
典型使用场景与示例
常见于避免重复字符串对象、节省内存,或确保字符串比较可用 ==(仅限已 intern 的字符串):
String s1 = new String("hello"); // 堆上新建对象
String s2 = s1.intern(); // 将 "hello" 加入常量池(若尚无),返回池中引用
String s3 = "hello"; // 字面量,直接从常量池获取
System.out.println(s2 == s3); // true:s2 和 s3 指向同一个池中对象
System.out.println(s1 == s2); // false:s1 是堆对象,s2 是池中引用
注意事项和陷阱
使用 intern() 需谨慎:
- 不是所有字符串都适合 intern:频繁调用或对长/动态字符串 intern 可能导致常量池膨胀,甚至 OOM(尤其 JDK 6 及以前,常量池在永久代)
- 只对内容确定、生命周期长、复用率高的字符串有效:比如解析配置项、协议关键字、枚举标识符等
-
intern() 不改变原对象本身:
s1.intern()不会让s1自动指向池中对象,必须显式赋值给变量(如s2 = s1.intern()) - 线程安全:intern 是 JVM 级原子操作,多线程调用无需额外同步
如何验证是否成功进入常量池
可通过 == 对比字面量来间接验证:
- 若
str.intern() == "xxx"为 true,说明str内容已存在于常量池(或刚被加入) - 注意:不能用
str == "xxx"判断,因为str本身可能仍是堆对象 - 调试时可配合 JConsole 或 JVM 参数
-XX:+PrintStringTableStatistics(JDK 8u20+)查看常量池状态
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











