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()的新行为:
new String("2") + new String("2")本质是通过StringBuilder的append()和toString()生成最终的"22"字符串。这个过程会在堆内存里创建一个值为"22"的字符串对象,但此时常量池里并没有"22"——因为拼接的结果不会自动进入常量池。- 调用
c.intern()时,JVM检查常量池发现没有"22",这时候JDK1.8的intern()不会像JDK1.6那样复制新对象到常量池,而是直接把堆里c指向的那个"22"对象的引用存入常量池。 - 执行
String d = "22"时,JVM去常量池查找"22",发现常量池里存的是堆中c对象的引用,所以d直接指向堆里的这个对象——和c指向同一个对象。 - 因此
c == d比较的是同一个对象的引用地址,自然返回true。
补充一句:如果是在JDK1.6中,intern()会把堆里的字符串复制一份放到永久代的常量池里,那第二个例子的c和d会指向不同对象,输出就是false了。
内容的提问来源于stack exchange,提问作者H.William
相关产品推荐
相关产品推荐

