在构造函数中传递的String文字在哪里,在我们创建新的String对象时存储

时间:2015-07-16 10:13:16

标签: java string jvm string-pool

在我们写的时候用Java编写

String S1 = "TestString";
String S2 = "TestString";

然后与if(S1==S2)进行比较,我们得到布尔结果的真实。 同样的解释是字符串常量是在字符串池中创建的,因此它是S1和S2在这里引用的相同的字符串常量。 另外,如果我们写一些类似

的内容
String S1 = new String("TestString");

String S2 = new String("TestString");

然后与if(S1==S2)进行比较,我们得到了错误。 原因是S1和S2的引用不同,因为字符串文字是在堆中创建的。

我的问题是,在构造函数中创建的String文字“TestString”在哪里? 它与String文字/常量相同吗?因此应该像案例1中那样在池中创建? 如果是,那么当我们写出类似于上述两个陈述之后

String S3 = "TestString";

这不应该创建一个新的字符串文字,比较if(S1==S3)应该给我真实,但它给出了错误。

所以我无法弄清楚在创建的构造函数中传递的字符串文字的位置和时间。

非常感谢任何帮助。 感谢

2 个答案:

答案 0 :(得分:4)

  

我的问题是,在构造函数中创建的String文字“TestString”在哪里?它与String文字/常量相同吗?因此应该像案例1中那样在池中创建?

正确,传递给构造函数调用new String("TestString")的常量字符串存储在字符串池中,就像语句String S1 = "TestString"中一样。

String S1 = new String("TestString");

String S2 = new String("TestString");

String S3 = "TestString";

在这种情况下,S1==S3给出false,因为S3引用由S1使用的构造函数的参数创建的字符串文字,而S1是不同的字符串(因为它是使用构造函数创建的)。

答案 1 :(得分:0)

  

if(S1 == S2),我们得到假。

那是因为你有三个不同的字符串,S1,S2和字符串文字。 S1和S2是String对象的副本,并具有不同的引用。因此,他们中没有一个是==彼此。

  

我的问题是在创建的构造函数中传递的String文字“TestString”在哪里?

它像所有其他对象一样在堆上创建(自Java 6起) 它也被添加到String intern()池中,因此任何其他字符串文字也是同一个对象。

  

它与字符串文字/常量相同吗?

具有相同内容的所有String文字将是同一个对象。

  

String S3 =“TestString”;这不应该创建一个新的字符串文字

正确。字符串文字已经创建。

  

比较if(S1 == S3)应该给我真实的

我不知道为什么。 S1是字符串文字的副本,而不是字符串文字本身。

  

但它给出了错误。

正如所料。

  

所以我无法弄清楚在创建的构造函数中传递的字符串文字的位置和时间。

在Java 7之前,在加载类时创建了字符串文字,在Java 7+中它是在第一次使用时创建的。

  

如果S1和S3共享相同的字符串文字/常量

直到Java 6,他们共享相同的底层char []。从Java 7开始,情况并非如此。 String对象一直都是并且将永远不同。

  

S1有引用,即它存储实际存储常量“TestString”的地方的内存地址

S1是一个副本,因此它存储了字符串文字副本的引用。

  

我仍然有一个问题,但是当我们比较S1和S3参考方式时,为什么它们不相等(它们必须保持相同的内存地址)

他们有不同的地址,这就是==给出错误的原因。

  

S1和S2都在堆栈中,它们包含它们从堆中引用的各个对象的地址值。因此S1和S2本身将占据不同的位置(地址)。

名义上S1S2具有不同的位置并指向不同的位置。但是,当代码在机器代码中被转换为实际运行时,它可以被优化,使得变量在寄存器中,而不是在堆栈上,并且丢弃任何未使用的变量。即可能没有任何物体存在。