字符串引用?

3
我们创建了以下String对象吗?
String str1 = new String("ABC");
String str2 = new String("ABC");
String str3 = "ABC";
String str4 = "ABC";

以上有两个问题:

  1. system.out.println("valof str1 "+str1 ); -- 它会将 str1 输出为 ABC 但是当我们比较 if(str1==str2) 时,它会比较字符串对象的引用。JVM 如何区分呢?

  2. str1str2 有不同的引用,而 str3str4 则有相同的引用,那么 JVM 是否会检查我们要用等号运算符创建的字符串是否已经存在(如果存在,则不会创建新的对象,只会将相同的引用赋给新变量,即 str4),但是在使用 new 运算符的情况下,它并不进行这种验证吗?

2个回答

11
在Java中,字符串字面值(裸的"ABC"而不是new String("ABC"))被“interned”(即在JVM中只存储一份副本,并且始终使用该副本)。这就是为什么它们在使用==时相等的原因。
以下比较也始终为真:
str1.intern() == str2.intern()
str1.intern() == str3
str2.intern() == str3
str1.intern() == str4
str2.intern() == str4

你可以调用 s.intern() 来使任何字符串进行内部化。 - Spike Gronim
@Spike:确实,我更新了我的答案来证明这一点。(我本来就计划在一开始就加入这个,但由于我想要第一个发帖——“西部最快枪手”——我通常会发布一些基本的东西,然后在5分钟的宽限期内扩展它。) - C. K. Young
感谢Chris提供深入的解释。但是我对你的解释有以下疑问:1)如果我们创建了str1 = new String(“ABC”)//它现在还没有添加到池中。正确吗?但是当我们执行str1.intern()时,它会将str1添加到池中。我的第一个问题仍未得到答复,即当我们执行if(str1 == str2)时,它比较引用,但在sys out中打印str1时,它实际上打印了值? - M Sach
@Mohit: 一个字符串不必被内部化才能被打印!只有在使用==进行比较时才需要将其内部化。否则,无论您是内部化字符串还是不内部化字符串都没有区别。 - C. K. Young
相关链接:https://dev59.com/Gmkw5IYBdhLWcg3ws873#9698305 - Michael Berry
1
@berry120 恭喜你在最近的一个问题上获得了56个赞!;-) - C. K. Young

3

当您调用new String(...)时,您将显式创建新字符串并请求不同的引用。如果您想恢复到单个引用,则可以调用:

str1 = str1.intern();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接