Java中concat()返回的堆字符串调用intern()为何与原引用相等
Java String#intern() 输出true的底层逻辑说明
你运行的代码如下:
String s1 = new String("Hello"); String s2 = s1.concat("World"); String s3 = s2.intern(); System.out.println(s2 == s3); // returns true
你原本的认知对应Java 6及更早版本的intern实现规则,Java 7之后字符串常量池(SCP)的存储位置和intern逻辑做了调整,是该输出结果的核心原因:
- Java 6及更早版本中SCP位于永久代,调用intern时如果常量池没有对应字符串,会复制当前堆对象的内容到永久代生成新对象,返回新对象的引用,此时s2 == s3会输出false
- Java 7及之后版本SCP移到堆空间,intern逻辑优化为:如果常量池中没有和当前字符串内容相等的引用,会直接把当前堆中字符串对象的引用存入常量池,不会额外创建新对象,返回值就是原堆对象的引用
- 你的代码执行时,s2是堆中生成的
HelloWorld对象,调用s2.intern()前常量池没有对应HelloWorld的引用,因此intern方法直接将s2的引用存入常量池,返回的s3和s2指向完全相同的对象,==比较结果为true
可以通过以下对比代码验证该逻辑:
// 提前通过字面量在常量池创建HelloWorld对象 String pre = "HelloWorld"; String s1 = new String("Hello"); String s2 = s1.concat("World"); String s3 = s2.intern(); // 此时intern返回常量池已有的pre对象引用,和堆中的s2不是同一个对象 System.out.println(s2 == s3); // 输出false
内容的提问来源于stack exchange,提问作者Ayush
相关产品推荐
相关产品推荐

