String.intern() 到底干了什么

String.intern() 是 JDK 6 开始有的方法,面试经常被问到,但很多人只停留在"字符串驻留"这个概念上,具体怎么回事不太清楚。

一、intern 的基本行为

调用 intern() 后,如果字符串池里已经有一个等于此对象的字符串,直接返回池里的那个;如果没有,把此对象加入字符串池,返回池里的引用。

java 复制代码
String s1 = new String("abc");
String s2 = s1.intern();

System.out.println(s1 == s2);  // false:s1 是堆对象,s2 是池里的

但 intern 用不好容易踩坑。

二、一个经典面试题

java 复制代码
String s1 = new String("a") + new String("b");
String s2 = s1.intern();

String s3 = new String("ab");
System.out.println(s1 == s2);  // true 还是 false?

先说答案:JDK 6 是 false,JDK 7+ 是 true。

解释一下执行过程:

JDK 6:

  • s1 = new String("a") + new String("b") 在堆里创建两个对象 "a" "b",拼接后生成 "ab",s1 指向堆
  • s2 = s1.intern() 把 "ab" 复制一份到字符串池,返回池地址给 s2
  • s1 在堆,s2 在池,所以 s1 == s2 是 false

JDK 7+:

  • s1.intern() 不再复制字符串到池,只是记录一下引用
  • 字符串池搬到了堆里,"ab" 本身就是从堆里产生的,直接记录引用就行
  • 所以 s1 和 s2 指向同一个对象,s1 == s2 是 true

三、intern 能省内存

适用场景:大量重复的字符串,只存一份能省不少内存。

java 复制代码
// 假设有 100 万个 userName,但实际取值只有几千种
String[] names = new String[1000000];
for (int i = 0; i < 1000000; i++) {
    names[i] = new String(getUserName()).intern();
}

intern 后,所有相同的字符串都指向字符串池里的同一个对象,内存占用会降下来。

但要注意:intern 会把字符串放入字符串池,如果取值种类太多(比如 UUID),反而浪费字符串池的内存。

四、常见用法:字符串比较

用 intern 做字符串字面量比较:

java 复制代码
// 不用 intern:每次比较都要遍历字符数组
if (str.equals("POST")) { }

// 用 intern:直接比较引用
if (str.intern() == "POST") { }

在高频比较场景下,引用比较比 equals 更快。

五、JDK 8 的陷阱

JDK 8 里字符串拼接和 intern 的交互比较绕:

java 复制代码
String a = "ab";
String b = "cd";
String c = "abcd";
String d = a + b;       // 编译期不会优化,结果是 new StringBuilder().append(a).append(b).toString()
String e = "ab" + "cd"; // 编译期直接优化成 "abcd"

System.out.println(c == d);  // false:c 是池,"abcd",d 是堆 new 出来的
System.out.println(c == e);  // true:e 在编译期就优化成 "abcd",也是池里的

所以 "ab" + "cd"a + b 看起来一样,但执行时机完全不同。

六、什么场景适合用 intern

场景 用 intern 原因
大量重复的字符串 节省内存
高频字符串比较 引用比较比 equals 快
取值种类极多的字符串 X 浪费字符串池空间
动态生成的字符串 X intern 本身也有开销

总结

  1. intern 返回字符串池里的引用
  2. JDK 6 会复制字符串到池,JDK 7+ 只是记录引用
  3. 用好了能省内存、做快速比较
  4. 用不好(取值种类太多)反而浪费内存

大多数业务代码里其实不太需要自己调用 intern,但如果面试问到,知道原理比背答案有用。

相关推荐
421!3 小时前
GPIO工作原理以及核心
开发语言·单片机·嵌入式硬件·学习
摇滚侠3 小时前
JAVA 项目教程《苍穹外卖-12》,微信小程序项目,前后端分离,从开发到部署
java·开发语言·vue.js·node.js
楚国的小隐士3 小时前
为什么说Rust是对自闭症谱系人士友好的编程语言?
java·rust·编程·对比·自闭症·自闭症谱系障碍·神经多样性
AI成长日志3 小时前
【笔面试算法学习专栏】双指针专题·简单难度两题精讲:167.两数之和II、283.移动零
学习·算法·面试
@insist1233 小时前
网络工程师-生成树协议(STP/RSTP/MSTP)核心原理与应用
服务器·开发语言·网络工程师·软考·软件水平考试
春花秋月夏海冬雪3 小时前
代码随想录刷题 - 贪心Part1
java·算法·贪心·代码随想录
野生技术架构师4 小时前
2026年牛客网最新Java面试题总结
java·开发语言
环黄金线HHJX.4 小时前
Tuan符号系统重塑智能开发
开发语言·人工智能·算法·编辑器
dog2504 小时前
对数的大脑应对指数的世界
开发语言·php