您的位置:首页 >String.intern()方法详解:手动入池技巧
发布于2026-02-14 阅读(0)
扫一扫,手机访问
String.intern() 返回常量池中已存在字符串的引用,内容相同即复用;若不存在则将当前字符串内容放入池并返回其引用,与是否为字面量无关。

它不总返回常量池里的“新”对象,而是返回池中已存在字符串的引用;如果不存在,才把当前字符串(注意:是当前 String 对象的字符内容)放入池,并返回该引用。关键在于“内容相同即复用”,和你调用的是不是字面量无关。
常见错误现象:"abc".intern() == "abc" 是 true,但 new String("abc").intern() == new String("abc") 是 false —— 因为右边是堆上新对象,左边是常量池引用,两者地址不同。
null 调用会抛 NullPointerExceptionJDK 6 把字符串常量池放在永久代(PermGen),空间小且不可扩容;JDK 7 起移到 Java 堆,受 GC 管理,行为更可控。这意味着在 JDK 6 中滥用 intern() 容易触发 java.lang.OutOfMemoryError: PermGen space,而 JDK 7+ 更多是堆内存压力。
典型误判:以为 intern() 总能“省内存”,其实它只是把字符串从堆某处挪到常量池——如果原对象还被强引用着,反而多占一份。
intern()-XX:+UseG1GC 后,常量池回收更积极,但依然不会回收仍被引用的 interned 字符串jmap -histo:live <pid> 查看 java.lang.String 实例数,配合 jstat -gc <pid> 观察老年代变化因为 String.valueOf(null) 返回的是字符串 "null",而 null.toString() 直接抛 NullPointerException。哪怕 x 是非 null 对象,valueOf 可能调用 toString(),但也可能走分支逻辑(比如 String.valueOf(char[]) 直接构造新字符串)。
容易踩的坑:用 intern() 做 key 归一化时,没统一入口,导致相同语义的字符串进了两次常量池。
String.valueOf(x) 替代 x.toString() 做空安全转换Integer 等包装类,String.valueOf(42) 和 42 + "" 都会生成新对象,再 intern() 才进池intern() 效果有限:除非大量重复数值(如状态码 "200"、"404"),否则性价比低它不是万能的“加速器”。很多场景下,用 equals() 或 ==(仅限确定是字面量或已 intern 过)更直接可靠。
intern()?高并发下锁竞争会让它变慢StringBuilder.toString() 却没 intern()),比较就会失效最常被忽略的一点:常量池里的字符串,只要被任何地方强引用着,就不会被 GC;而堆上字符串可以随时回收。所以“省内存”是有代价的——换来的可能是更难排查的内存泄漏。
上一篇:德邦快递单号查询及包裹追踪方法
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9