Java字符串相等示例
事先很抱歉问了一个基本问题,但有人能解释一下原因吗:Java字符串相等示例,java,string,Java,String,事先很抱歉问了一个基本问题,但有人能解释一下原因吗: String s = "lo"; String str7 = "Hel" + s; String str8 = "He" + "llo"; System.out.println("str7 == str8 is " + (str7 == str8)); 输出为假。 我认为str7和str8都指向字符串池中的同一个对象,特别是因为字符串是不可变的 我错了吗? str7和str8是否都不在池中,而是在堆中?为什么? 您能给我提供一些字符串操作的
String s = "lo";
String str7 = "Hel" + s;
String str8 = "He" + "llo";
System.out.println("str7 == str8 is " + (str7 == str8));
输出为假。
我认为str7和str8都指向字符串池中的同一个对象,特别是因为字符串是不可变的
我错了吗?
str7和str8是否都不在池中,而是在堆中?为什么?
您能给我提供一些字符串操作的例子吗?当结果确实是字符串池中的同一个不可变字符串时
附言:
输出true
str7
和str8
都在池中,但它们不是相同的字符串。也就是说,它们是相同字符序列的不同版本
想想如果VM每次创建一个字符串时都必须扫描整个池,以查看是否已经存在另一个具有相同字符序列的字符串,那么会对性能造成多大的影响
在您的新示例中,您正在从相同的基础字符串构建str8
和str9
,因此编译器可以更容易地判断每个字符串的结果是相同的,并且可以在池中重复使用该项。如果您调用,那么编译器将扫描字符串
池,并按照您的预期执行。就是
String s = "lo";
String str7 = ("Hel" + s).intern();
String str8 = ("He" + "llo").intern();
System.out.println("str7 == str8 is " + (str7 == str8));
输出
str7 == str8 is true
导致这种行为的原因有两个
String
是不可变的,因此使用+
必须创建新的字符串
String
连接通常通过StringBuilder
实现,即new StringBuilder(“Hel”)。append.toString()
和new StringBuilder(“He”)。append(“llo”)。toString()
和StringBuilder
不扫描字符串
内部池对于所有文本都进入字符串池的池,您的理解是正确的 在进行连接时会出现混淆。这里有两点需要注意 1) 如果字符串在编译时解析,那么它将与字符串池同步并使用相同的文本。前
String str7 = "Helllo";
String str8 = "He" + "llo";
请注意,两者都是纯文本。因此没有运行时转换等
2) 如果字符串在运行时解析,则它在运行时解析为新字符串,并与任何其他字符串不同,除非使用.equals方法比较其内容
String str7 = "Hel" + s;
String str8 = "He" + "llo";
System.out.println("str7 == str8 is " + (str7 == str8)); //false
在本例中,带有(+)运算符的concat字符串,JVM返回新的StringBuilder(字符串…).toString()
,因为一个是纯文本,另一个是变量
看这张照片
如果只有一个操作数表达式为String类型,则在运行时对另一个操作数执行字符串转换(§5.1.11),以生成字符串
评论中的问题:
这是否意味着,如果字符串是文字串联的产物,那么结果在池中总是相同的字符串
是的。请记住,串联指的是编译时解析表达式(也称为常量表达式),而不是运行时
当我们将字符串文字与字符串对象连接起来时,得到的字符串总是一个通过StringBuilder在后台构建的新字符串对象
是,返回了一个新字符串。附加的JVM链接证实了这一点
String s = "lo";
String str7 = "Hel" + s;
String str8 = "He" + "llo";
String str9 = "He" + "llo";
s
引用的对象是表示“lo”文本的字符串对象。它在字符串池中
str8
和str9
引用的对象是对常量表达式求值的结果。因此,它们在字符串池中。事实上,由于表达式的计算结果是“相同的”字符串,str8
和str9
引用的是相同的实际string
对象
str7
引用的对象是对非常量表达式求值的结果。因此,它不在字符串池中
“Hel”+s
在这里不是一个常量表达式的最终原因是s
没有声明为final
这里要记住的是,字符串对象仅在两种情况下分配到字符串池中:
String.intern()
方法显式生成的任何在这些情况下不产生的字符串都不在字符串池中。@RajithPemabandu:但问题是关于底层表示的;使用
equals
是为了避免这些细节。str8==str9的原因与编译器优化有关:对不起,斯科特-我完全困惑和不知所措。“同一字符序列的不同版本”在池中的确切含义是什么?至于扫描整个池,我认为这正是拥有字符串池的目的;编译器平衡了查找匹配字符串(通常会失败)的成本和重复使用字符串的好处。您似乎了解“相同字符序列的不同版本”是什么这意味着可以对此进行争论:两个不同的字符串占据了内存中的不同位置,它们碰巧具有相同顺序的相同字符。这是不正确的<代码>str7不在字符串池中。它不是常量表达式的结果,也没有被显式插入。我知道intern()的含义,多亏了这个问题,为什么这两个字符串s7和s8指向同一位置的不同字符串-字符串pool@AndreyM.Stepanov我希望我的两个要点能澄清为什么。。。Stephen C解释了为什么s7和
String s = "lo";
String str7 = "Hel" + s;
String str8 = "He" + "llo";
String str9 = "He" + "llo";