string.intern()可将运行时字符串显式映射到jvm字符串常量池,若池中已存在相同内容(equals判断)则返回池中引用,否则加入并返回;适用于内容高度重复、生命周期长且可控的场景,但滥用会导致常量池膨胀和gc压力。

intern() 方法能将字符串对象尝试加入字符串常量池,如果池中已存在相同内容的字符串(通过 equals() 判断),就返回池中那个引用;否则把当前字符串加入池并返回其引用。它不自动“优化内存”,而是帮你**复用已有字符串对象**,避免重复创建内容相同的字符串实例。
什么时候调用 intern() 才有意义
只有当多个字符串内容相同、但来源不同(比如从数据库、网络、文件读取或拼接生成),且你确定后续会频繁比较或长期持有时,才值得考虑 intern()。盲目调用反而可能增加 GC 压力(尤其在老版本 JDK 中常量池在永久代)。
- 从 JSON 或 CSV 解析出大量重复字段名(如 "status"、"id"、"name")
- 日志中提取的固定级别标签(如 "ERROR"、"INFO")
- 用户输入中可枚举的有限取值(如国家代码、状态码)
基本用法和效果验证
直接调用 String.intern() 即可:
String s1 = new String("hello"); // 堆上新建对象
String s2 = "hello"; // 常量池中已有字面量
String s3 = s1.intern(); // 返回常量池中的 "hello"
System.out.println(s2 == s3); // true(同一对象)
System.out.println(s1 == s2); // false(s1 在堆,s2 在常量池)
System.out.println(s1.equals(s2)); // true(内容相同)
注意:== 比较的是引用是否相同,intern() 的价值正体现在让语义相同的字符串指向同一个对象。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
JDK 版本差异与注意事项
Java 7 起,字符串常量池被移到堆内存中,intern() 性能更稳定,GC 可回收不再使用的常量池字符串;而 Java 6 中常量池在永久代,容易导致 OutOfMemoryError。
- 不要对随机、不可控长度的字符串(如用户昵称、长文本)调用
intern(),可能撑爆堆 -
intern()是本地方法,有同步开销,高并发场景下需评估性能影响 - 字符串字面量(如
"abc")本身已在常量池中,无需再调用intern()
更安全的替代思路
若想控制字符串复用逻辑,又不想依赖 JVM 常量池行为,可用 ConcurrentHashMap 自建字符串规范器:
private static final ConcurrentHashMap<string string> STRING_POOL = new ConcurrentHashMap();
public static String pool(String s) {
return STRING_POOL.computeIfAbsent(s, k -> k);
}</string>
这种方式可控、可清理、线程安全,适合业务侧明确管理字符串生命周期的场景。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










