You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JDK1.8下String.intern()执行结果差异的原因咨询

为什么JDK1.8中第二个字符串比较会输出true?

嘿,这个问题的核心在于JDK 1.8对String.intern()方法的行为调整,我来一步步给你拆解清楚:

先理解第一个输出false的逻辑

先看这段代码:

String a = new String("11") ; 
a.intern(); 
String b = "11"; 
System.out.println(a == b); // false
  • 执行new String("11")时,JVM会先在字符串常量池里创建一个值为"11"的字符串对象,再在堆内存里创建另一个内容相同的字符串对象,变量a指向堆里的这个对象。
  • 调用a.intern()时,JVM发现常量池里已经存在"11",所以这个方法啥也没做,直接返回常量池里的对象引用(我们没接收这个返回值,不影响后续逻辑)。
  • 执行String b = "11"时,JVM直接让b指向常量池里已有的"11"对象。
  • 所以a(堆对象)和b(常量池对象)是两个不同的对象,==比较引用地址自然返回false。

重点解析第二个输出true的原因

再看这段关键代码:

String c = new String("2") + new String("2"); 
c.intern(); 
String d = "22"; 
System.out.println(c == d); // true

这里的核心是字符串拼接的底层逻辑,以及JDK1.8中intern()的新行为:

  1. new String("2") + new String("2")本质是通过StringBuilder的append()和toString()生成最终的"22"字符串。这个过程会在堆内存里创建一个值为"22"的字符串对象,但此时常量池里并没有"22"——因为拼接的结果不会自动进入常量池。
  2. 调用c.intern()时,JVM检查常量池发现没有"22",这时候JDK1.8的intern()不会像JDK1.6那样复制新对象到常量池,而是直接把堆里c指向的那个"22"对象的引用存入常量池。
  3. 执行String d = "22"时,JVM去常量池查找"22",发现常量池里存的是堆中c对象的引用,所以d直接指向堆里的这个对象——和c指向同一个对象。
  4. 因此c == d比较的是同一个对象的引用地址,自然返回true。

补充一句:如果是在JDK1.6中,intern()会把堆里的字符串复制一份放到永久代的常量池里,那第二个例子的c和d会指向不同对象,输出就是false了。

内容的提问来源于stack exchange,提问作者H.William

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:43:06