将两个字符串与“==”进行比较:它何时起作用?
假设你有三个字符串,
String s1 = "string one"; String s2 = new String("string one"); String s3 = "string one";
我知道s1 == s2
是false
,但我在某处读到了s1 == s3
为true
。 它是否正确? 为什么或者为什么不?
字符串文字自动实现。 因此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运行时变量使用堆空间。