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

JDK1.8下String常量池测试结果疑惑及技术咨询

JDK1.8 String常量池问题解析

先看测试代码:

// Test1
String sa = new String("lmn");
String sa1 = new String("opq");
StringBuilder stringBuilder = new StringBuilder().append(sa).append(sa1);
String sa2 = stringBuilder.toString();
String sa3 = sa2.intern();
String sa4 = "lmnopq";
System.out.println("sa2 == sa3 ? " + (sa2 == sa3)); // true  why?
System.out.println("sa3 == sa4 ? " + (sa3 == sa4)); // true

// Test2
String sss = new String("ghi") + new String("hjk");
String sss1 = sss.intern();
System.out.println("sss == sss1 ? " + (sss == sss1)); // true why?

// Test3
String sc = new String("rszt") + new String("zuvw");
String sc1 = "rsztzuvw";
String sc2 = sc.intern();
System.out.println("sc == sc1 ? " + (sc == sc1)); // false why?

问题1:为何sa2 == sa3成立?"lmnopq"何时存入String常量池?

  • JDK1.8中String.intern()的逻辑是:检查常量池是否存在内容匹配的字符串。如果不存在,直接将堆中当前字符串的引用存入常量池,而非复制新对象到常量池。
  • sa2是StringBuilder.toString()生成的堆字符串,此时常量池中还没有"lmnopq"。调用sa2.intern()时,因常量池无匹配项,sa2的引用被存入常量池,sa3作为intern()的返回值,就是sa2本身的引用,因此sa2 == sa3成立。
  • "lmnopq"存入常量池的时机就是调用sa2.intern()的时候。后续sa4 = "lmnopq"会直接引用常量池中的sa2引用,所以sa3 == sa4也成立。

问题2:sss == sss1的原因是否与sa2 == sa3一致?

  • 完全一致。
  • new String("ghi") + new String("hjk")被优化为StringBuilder.append()后,sss本质就是StringBuilder.toString()生成的堆字符串,此时常量池中没有"ghihjk"。调用sss.intern()时,同样因常量池无匹配项,sss的引用被存入常量池,sss1返回的就是sss的引用,因此sss == sss1。

问题3:Test2与Test3逻辑相似,仅在sc.intern()前添加了String sc1 = "rsztzuvw";,为何此时sc != sc1?

  • String sc1 = "rsztzuvw";会先触发常量池初始化:JVM会创建"rsztzuvw"字符串对象并放入常量池,sc1直接引用常量池中的该对象。
  • 后续调用sc.intern()时,常量池中已存在"rsztzuvw",因此intern()直接返回常量池中的对象引用(即sc1的引用),而非sc的堆引用。sc是堆中对象,sc1是常量池对象,两者引用不同,所以sc == sc1为false。

内容的提问来源于stack exchange,提问作者Pai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 18:02:38