假设你有三个字符串,
String s1 = "string one";
String s2 = new String("string one");
String s3 = "string one";
我知道s1 == s2
false
属于s1 == s3
,但我读到的地方true
是{{1}}。它是否正确?为什么或为什么不呢?
答案 0 :(得分:22)
字符串文字自动实现。因此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最初是在堆中创建的。
答案 1 :(得分:4)
是的,这是事实,因为字符串文字都是实体。有关详细信息,请阅读String.intern()
的文档。
因此,这些都是相同的对象(并且将与==
进行比较):
s1
s3
s1.intern()
s2.intern()
s3.intern()
答案 2 :(得分:1)
以上是如何。
你应该知道原因。
A)在编译时声明的字符串变量ref常量池中的常量
B)字符串变量结果由方法引用堆空间中的Object。
这一切都是因为JVM规范和它的内存设计。
A)因为字符串是不可变的。当java编译类和jvm加载类时,jvm找到了一个由你的编码时间声明的String变量。因为它是常量,jvm将常量放到“Runtime Constant Pool”内存区域。并且,常数是唯一的。
B)是简单的。因为jvm运行时变量使用堆空间。