考虑以下代码
String s1 = "testString";
String s2 = "testString";
if(s1 == s2)System.out.println("equals!");
它打印等于!,(我知道编译器的字符串实习)
String[] s1 = {"testString","teststring2"};
String[] s2 = {"testString","teststring2"};
if(s1 == s2)System.out.println("equals!");
但是上面的代码不起作用,为什么java编译器没有实习字符串数组?
答案 0 :(得分:4)
原因是String
是不可变的。您无法在不创建新实例的情况下对其进行更改。因此,尽可能使用相同的实例来匹配字符串是安全的。 Strings are constant; their values cannot be changed after they are created.
阵列是一个不同的故事。您可以更改数组,只需为其中一个字段分配新值。
s1[0] = "testString3"
如果编译器对s1
和s2
使用相同的实例,则会自动更改两个数组。这可能不是你想要做的事情。这就是数组没有被实习的原因。
请注意,字符串实习可能有限制,具体取决于编译器,编译器可能会选择不实际执行某些字符串,具体取决于字符串的数量或字符串的长度。有一个内部字符串表由JVM选项+XX:StringTableSize=n
控制,它确定用于存储实习字符串的字符串表的大小。
当归结为比较字符串时,使用equals函数总是更好。在执行更昂贵的检查之前,大多数实现首先检查引用相等性。
修改强>
所以实际上我声称内置字符串的存储空间增长似乎是错误的。 String.intern()
方法的文档表明此函数将确保将字符串添加到唯一字符串池中。意味着这个游泳池无法满员。 @Holger写道,内部实现使用类似某种结构的哈希映射。这支持了这种说法。
因此,JVM将根据JLS §3.10.5将所有常量字符串存储在实际哈希表中。
字符串文字始终引用类String的相同实例。这是因为字符串文字 - 或者更一般地说,字符串是常量表达式的值... - 是" interned"以便使用String.intern
方法共享唯一的实例
所有这些,请仍然习惯字符串类的equals
方法来检查字符串是否相等。该方法将利用这样的事实:在执行更昂贵的长度和字符检查之前,字符串可以是相同的参考并且在这种情况下非常快地完成。使用此方法总是更好。在未来的java版本中,字符串的处理方式可能会也可能不会改变。使用equals
方法,您可以放心使用。
答案 1 :(得分:-2)
您无法将String数组与 == (如String)进行比较。实习生仅适用于String。如果要比较字符串数组,请尝试此Java, how to compare Strings with String Arrays