当前位置: 首页 > 知识库问答 >
问题:

关于java字符串文字池和字符串连接的混淆

丁雅惠
2023-03-14

当我写下面的代码时,我遇到了一个问题

String hello = "Hello";
String str5 = "Hel" + "lo";
String str8 = "Hel";
String str9 = "lo";
String str10 = str8 + str9;
System.out.println("str10==hello?" + (str10 == hello)); 
System.out.println("str5==hello?" + (str5 == hello));
System.out.println("str10==str5?" + (str10 == str5));

然后我运行我的代码,控制台打印这个

str10 == hello ? false
str5 == hello ? true
str10 == str5 ? false

这让我很困惑。为什么第二次打印是真的,而第一次打印是假的??在我对String文字池的理解中,当定义一个字符串时,JVM将检查池中是否包含该字符串,如果不包含,则将该字符串放入池中。
在我的代码中,变量Hello存在于字符串池中,“Helo”和“lo”也在池中,我的问题是

  1. 如果池中存在Helo和lo串联的结果。
  2. 关于str5和str10s的定义有什么区别,为什么它们不是==?str5和str10是指字符串池中的不同的Hello吗?(=="似乎意味着引用是同一个对象)

我的jdk版本:1.6。0_29
我的IDE:Intellij Idea 11.2

有人能指出吗?非常感谢你

共有3个答案

高恺
2023-03-14

该准则有以下几点需要考虑:

String hello = "Hello";

这里“Hello”是一个分配给reference Hello的文本,因此该文本有自己的hashcode

String str5 = "Hel" + "lo";

这里的“Hel”“lo”是两个字面值的组合,并分配给reference hello,因此新字面值与第一个字面值相同,因此哈希代码相同

String str8 = "Hel";
String str9 = "lo";

这里str8和str9是两个引用,它们组合并指向一个新的引用hello,因此新的文本有自己的hashcode

String str10 = str8 + str9;
System.out.println("str10==hello?" + (str10 == hello)); 
System.out.println("str5==hello?" + (str5 == hello));
System.out.println("str10==str5?" + (str10 == str5));

当您使用==时,它通过哈希代码和值匹配。因此,不匹配。

尝试使用

字符串_1。等于(字符串_2)

而不是

字符串_1==字符串_2

你将只得到价值匹配。因此都是真的

请参考以下答案(Java中==vs equals()之间的区别是什么?):

equals()方法比较字符串实例(堆上)内的“值”,而不管两(2)个对象引用是否引用同一个字符串实例。如果任何两(2)个String类型的对象引用引用同一个String实例,那就太好了!如果两(2)个对象引用引用了两(2)个不同的字符串实例。。这没什么区别。它是被比较的每个字符串实例中的“值”(即:字符数组的内容)。

另一方面,“==”操作符比较两个对象引用的值,以查看它们是否引用同一个字符串实例。如果两个对象引用的值“引用”同一个字符串实例,则布尔表达式的结果将为“true”。。嗯。另一方面,如果两个对象引用的值“引用”不同的字符串实例(即使两个字符串实例具有相同的“值”,即每个字符串实例的字符数组的内容相同),则布尔表达式的结果将为“false”。

边健
2023-03-14
String hello = "Hello";       // at compile time string is known so in String Constant Pool

String str5 = "Hel" + "lo";   // at compile time string is known so in String Constant Pool same object as in variable hello

String str8 = "Hel";          // at compile time string is known so in String Constant Pool

String str9 = "lo";           // at compile time string is known so in String Constant Pool

String str10 = str8 + str9;   // at runtime don't know values of str8 and str9 so in String Constant Pool new object different from variable hello

str10 == hello ? false        // as str10 has new object and not the same as in hello

str5 == hello ? true          // both were created at compile time so compiler know what's the result in str5 and referenced the same object to str5 as in hello

str10 == str5 ? false         // str10 is a different object, hello and str5 are referenced same object as created at compile time.
璩涛
2023-03-14

它的行为应该是正常的。JLS中有两个章节对此进行了论述。

JLS#3.10。5:

作为常量表达式(§15.28)值的字符串被“驻留”,以便使用S方法共享唯一的实例tring.intern.

JLS#15.28列出了常量表达式。特别是,字符串文字是常量表达式(“Hel”和“lo”),但要将变量视为常量,它需要是最终的。

在您的情况下,如果您稍微更改代码以使str8str9保持不变,您将得到true三次:

final String str8 = "Hel";
final String str9 = "lo";
 类似资料:
  • 问题内容: 这与Java字符串常量池有关。在我的一个程序中,我正在解密数据库的密码并将其存储在字符串中。我听说Java字符串将存储在Constant池中,并且不会被VM重新启动或加载了String Quits的ClassLoader破坏。 如果是这种情况,我的密码将存储在字符串池中。我非常关心这个问题。还有其他方法可以销毁这些文字或我可以做的其他任何事情。 请对此提出建议, 问候,阳光明媚。 问题

  • 问题内容: 为什么在这些情况下输出不同? ==> 印刷:2010年 ==> 打印:200 为什么第一个输出不是30?它与运算符优先级有关吗?就像首先将“ printing”和x连接在一起,然后将结果字符串和y连接在一起?我对么? 问题答案: 它的规则 我在下面显示从高到低的优先顺序: **如果运算符具有相同的优先级 ,* 则 此方法起作用 * 现在 :是字符串” :是Java中唯一将Number连

  • 当使用关键字 new 创建字符串时,它使用采用 String 文本的构造函数创建新的 String 对象。我想知道在调用 String 构造函数之前,文本是否存储在常量池中。 我这么问的原因是,在《OCA Java SE 7程序员I认证指南》中,Mala Gupta写道: 她在第一行表示,new创建的String对象不会存储在常量池中。这很好,但不清楚的是,第一行构造函数中的字面“Summer”是

  • 我的问题很简单。有什么区别-

  • 问题内容: 问题1 在第一种情况下,我知道这是两个字符串文字的串联,因此将对结果“ I Love Java”进行检查,使结果为true。但是,我不确定第二种情况。 问题2 上面的返回false,但是如果我注释掉第1行和第2行,则返回true。这是为什么? 问题答案: 问题的第一部分很简单:Java编译器将多个字符串文字的串联视为一个字符串文字,即 和 是两个完全相同的字符串文字,可以正确地进行in

  • 问题内容: 这是以前有关Java中的String初始化的一些问题的后续问题。 在用Java进行了一些小测试之后,我面临以下问题: 为什么我可以执行此语句 当str2一个String对象初始化为,但我不能调用方法toString()上str2?那么Java如何将空字符串对象和字符串文字串联起来? 顺便说一句,我还尝试将一个初始化为null和字符串文字的Integer连接起来,”a_literal_s