首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java中的字符串互连、字符串连接和字符串常数池示例

java中的字符串互连、字符串连接和字符串常数池示例
EN

Stack Overflow用户
提问于 2020-12-02 06:01:04
回答 1查看 179关注 0票数 0
代码语言:javascript
复制
package com.lang;

class StringConcatDemo2
{
   public static void main(String[] args)
   {
      String s1 = "Hello".concat("World"); // s1 to be created in heap.
      String s2 = s1.intern(); //Line-2   //Since "HelloWorld" doesn't exist in String constant pool (SCP), s1 and s2 point the same.      
      String s3 = "HelloWorld"; //Line-3  s3 to be created in SCP.
      String s4 = s1.intern();  //Since "HelloWorld" exists in SCP, s3 & s4 should refer to String in SCP.
      System.out.println(s1 == s2); // true
      System.out.println(s1 == s4); // Expected false. But it is true.
      System.out.println(s1 == s3); // Expected false. But it is true. 
      System.out.println(s3 == s4); //true
   }
} 

为什么s1和s4在堆中引用相同的对象?为什么s1和s3在堆中引用相同的对象?当我交换Line-2和Line-3时,o/p符合我的预期(o/p: false,true)

有人能给我详细解释一下吗?

EN

回答 1

Stack Overflow用户

发布于 2020-12-02 07:32:04

由于JVM位于源文件中,因此生成的.class文件包含该字符串常量,并且在将类定义加载到"HelloWorld"中时,该字符串常量被添加到字符串常量池(SCP)。

这意味着我们期望s2s3s4都引用SCP中的字符串。

我不知道为什么"Hello".concat("World")最终会引用SCP实例,尽管这可能是在JVM中实现的优化,因为concat()是众所周知的字符串方法,而字符串是众所周知的占用内存的方法。

相反,"Hello" + "World"也应该引用SCP实例,因为Java编译器可以将该常量表达式求值为"HelloWorld",这在使用javap反汇编.class字节码时可以看到。

已更新

看起来我错了,.class文件中的字符串常量不是在装入类时添加到SCP中,而是在第一次使用字符串常量时添加到SCP中。

这意味着序列如下:

  1. s1分配了字符串"HelloWorld",该字符串不在SCP中。

  1. s1.intern()s1引用的字符串添加到SCP中,并为s2分配相同的引用值。

结果:s2 = s1

  1. 字符串常量"HelloWorld"由JVM解析,因为它已经在SCP中,所以会返回SCP实例。

结果:s3 = s1

  1. s3.intern()只返回s3,因为它已经在SCP中了。

结果:s4 = s3 = s1

结果如下所示:s1s2s3s4都引用了同一个对象。

如果代码的顺序改变了,结果就会不同,这会导致以下结果:

代码语言:javascript
复制
String s1 = "HelloWorld";
String s2 = s1.intern();
String s3 = "Hello".concat("World");
String s4 = s1.intern();
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s1 == s4); // true

解析

  1. String常量"HelloWorld"并添加到SCP中。将为s1分配SCP实例。

  1. s1.intern()只返回s1,因为它已经在SCP中了。

结果:s2 = s1

  1. concat()在堆中创建"HelloWorld"的新实例,并将其分配给s3

结果:s3 != s1

  1. s3.intern()s1引用的字符串添加到SCP中,并为s2分配相同的引用值。

结果:s4 = s1

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65099188

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档