将两个字符串与“==”进行比较:它何时起作用?

假设你有三个字符串,

String s1 = "string one"; String s2 = new String("string one"); String s3 = "string one"; 

我知道s1 == s2false ,但我在某处读到了s1 == s3true 。 它是否正确? 为什么或者为什么不?

字符串文字自动实现。 因此s1 == s3为真。 字符串可以在字符串常量池中创建,也可以在堆空间中创建。 如果您实际在堆中创建了一个字符串,则该字符串将位于字符串常量池中。

创建字符串文字(String s1 =“string one”)时,将在字符串常量池中创建字符串。 此外,字符串常量池不存储重复项。 所以,当你说,

 String s1 = "string one"; String s3 = "string one"; 

s1和s3都将指向字符串常量池中字符串的同一实例。 所以s1.equals(s3)将是真的。 而s1 == s3也是如此; 因为两个指针都是一样的。

但是,使用“new”构造函数实例化字符串时

 String s2 = new String("string one"); 

然后在堆空间中创建s2。 堆空间是与字符串常量池不同的内存区域

因此,当s1.equals(s2)为真时,s1 == s2为假; 因为他们将指向不同的记忆区域。

但是,您可以转换使用“new”构造函数创建的字符串,以通过调用intern()函数将其移动到字符串常量池。 所以s2.intern()将在字符串常量池中返回一个字符串; 虽然s2最初是在堆中创建的。

是的,这是事实,因为字符串文字都是实体。 阅读String.intern()的文档以获取更多详细信息。

因此,这些都是相同的对象(并将与==相等):

 s1 s3 s1.intern() s2.intern() s3.intern() 

以上是如何。

你应该知道为什么。

A)在编译时声明的字符串变量ref常量池中的常量

B)字符串变量结果由方法引用堆空间中的Object。

这一切都是因为JVM规范和它的内存设计。

A)是因为字符串是不可变的。当java编译类和jvm加载类时,jvm找到了一个由你的编码时间声明的String变量。因为它是常量,jvm将常量放到“Runtime Constant Pool”内存区域。 并且,常数是唯一的。

B)是简单的。 因为jvm运行时变量使用堆空间。