intern()方法将字符串引用手动加入常量池:若池中已存在equals相等的字符串则返回其引用,否则将当前字符串引用加入池并返回;jdk7+常量池在堆中,仅存引用不复制内容。

Java 中的 intern() 方法用于将字符串对象手动添加到运行时常量池(String Pool),前提是该字符串内容尚未存在于常量池中。
intern 的核心逻辑
调用 str.intern() 时,JVM 会检查字符串常量池中是否已存在一个与 str 内容(equals 比较)完全相同的字符串:
- 如果存在,直接返回常量池中那个字符串的引用;
- 如果不存在,就把当前字符串对象的引用(注意:不是复制内容,而是引用本身)放入常量池,并返回该引用。
注意:从 JDK 7 起,字符串常量池被移到堆内存中(不再是永久代),所以 intern() 操作的对象是堆中的字符串实例,只是在常量池中记录其引用。
什么时候 intern 会真正“放入”常量池
只有当常量池中**没有等值字符串**时,intern() 才会把当前字符串引用加入池中。例如:
String s1 = new String("hello"); // 堆中新对象
String s2 = s1.intern(); // "hello" 不在池中 → 把 s1 的引用放入池,s2 指向它
String s3 = "hello"; // 字面量,直接从池中获取 → s3 == s2 为 true
但如果池中已有相同内容:
String s4 = "world"; // 先定义字面量,进入池
String s5 = new String("world").intern(); // 池中已有 → 返回池中引用,不新增
System.out.println(s5 == s4); // true
intern 的实际用途和注意事项
主要适用于需要频繁比较、且字符串内容重复率高的场景(如解析大量配置键、HTTP 头名、枚举标识符等),可减少内存占用并加速 == 判断。
- 不要对任意用户输入无条件 intern —— 可能导致常量池膨胀甚至 OOM;
- intern 是本地方法,有一定开销,不宜高频调用;
- 字符串字面量(如
"abc")在类加载时自动入池,无需手动 intern; - 使用
intern()后,建议用==判断引用相等,但务必确保所有相关字符串都经过统一 intern 流程。
验证 intern 是否生效的小技巧
可通过 == 和 System.identityHashCode() 辅助判断:
String a = new String("test");
String b = a.intern();
String c = "test";
System.out.println(a == b); // false(a 是堆对象,b 是池中引用)
System.out.println(b == c); // true(指向同一对象)
System.out.println(System.identityHashCode(b) == System.identityHashCode(c)); // true
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











