字符串比较困惑

在我们继续之前: 我知道我们应该使用.equals()来比较内容。 我现在只是谈论以下场景的实际参考是否相同……

假设我们有以下内容:

String str1 = "str"; String str2 = "string"; String str3 = "ing"; String str4 = str1 + str3; str1 = str4; String str5 = "string"; System.out.println(str1==str2);//false 

我认为它应该是真的,因为在String池中,对“string”的引用应该是相同的,因为str1和str2现在都是“string”。 它应该是真的,但最终是假的

 System.out.println(str1.intern()==str2.intern());//true 

我试过这个,这次回归真实 。 然后我尝试了:

 System.out.println(str1==str5);//false System.out.println(str2==str5);//true 

还有System.out.println(“str”+“ing”==“string”); // true

是不是应该来自String池? 有人可以帮忙解释一下吗?

只保证汇总字符串文字和常量表达式。 由于str1 + str2不是文字,因此无论结果是否被实现,都取决于JVM。 你可以通过调用intern()来强制它,就像你已经发现的那样。

这在Java语言规范的第3.10.5节中定义:

字符串文字是对String类实例的引用(§4.3.1,§4.3.3)。

此外,字符串文字始终引用类String的相同实例。 这是因为字符串文字 – 或者更常见的是作为常量表达式(第15.28节)的值的字符串 – 被“实例化”以便使用String.intern方法共享唯一实例。

你的第二个例子, "str" + "ing" ,是一个常量表达式,所以它保证被实习。

另请参阅JavaDoc for String.intern

这是试图解释发生了什么。 编写良好的代码应该永远不会依赖于此,但始终使用equals方法。 任何合理的JRE都会有一张支票

 if (this == other) return true; 

非常接近String.equals的顶部所以性能明智,这应该没关系。

始终使用equals方法比较字符串。 实习的麻烦在于JDK的每个版本都有点不同,所以我不会指望它,除非你想每次都在字符串上调用实习生。

比较的工作原理如下:

 String str1 = "str";` //"str" is created in SCP and str1 is a reference to that String str2 = "string";` //"string" is created in SCP and str2 is a reference String str3 = "ing";` //"ing" is created in SCP and str3 is a reference String str4 = str1 + str3;//"string" will be created on Heap and str4 is a reference (this is because if any string created at runntime will always be created on Heap) (here SCP already has this "string" so no change) make a note that str4 is pointing to Heap string Object and not SCP str1 = str4; `// str1 and str4 will start pointing to same String Object on Heap String str5 = "string";` // SCP already has this and str2 pointing to that so now onwards str5 will also point to it based on above 1. str1 and str4 -- > are pointing to "string" object on heap 2. str2 and str5 -- > are pointing to "string" object in scp 3. str3 -- > is pointing to "ing" in scp and finally the corresponding output can be traced based on above lines: System.out.println(str1==str2);`//false System.out.println(str1.intern()==str2.intern());`//true System.out.println(str1==str5);`//false System.out.println(str2==str5);`//true System.out.println("str"+"ing"=="string");`//true as "str"+"ing" will be replaced by "string" at compile time only (constant)