为什么 java 编译器不实习数组?

Why java compiler does not interns arrays?

考虑以下代码

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编译器不实习字符串数组?

原因是String是immutable。如果不创建新实例,则无法更改它。因此,尽可能使用相同的实例来匹配字符串是安全的。 Strings are constant; their values cannot be changed after they are created.

数组是另外一回事。您可以更改数组,只需为其中一个字段分配一个新值即可。

s1[0] = "testString3"

如果编译器将对 s1s2 使用相同的实例,您将自动更改两个数组。这可能不是您想做的事情。这就是数组不被驻留的原因。

另请注意,字符串驻留可能有限制,具体取决于编译器,编译器可能会选择不驻留某些字符串,具体取决于字符串的数量或字符串的长度。有一个内部字符串 table 由 JVM 选项 +XX:StringTableSize=n 控制,它确定用于存储内部字符串的字符串 table 的大小。

当涉及到比较字符串时,使用等号函数总是更好。大多数实现首先检查引用相等性,然后再执行更昂贵的检查。

编辑:

所以实际上我关于驻留字符串的存储空间变满的说法似乎是错误的。 String.intern() method indicates that this function will make sure that the string is added to the pool of unique strings. Means that there is no way that this pool will be full. @Holger 的文档写道,内部实现使用某种类似哈希图的结构。这支持了这一说法。

因此 JVM 将根据 JLS §3.10.5 将所有常量字符串存储在 interned 哈希 table 中。

a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions …- are "interned" so as to share unique instances, using the method String.intern

话虽这么说,但请仍然习惯字符串 class 的 equals 方法来检查字符串是否相等。该方法将利用这样一个事实,即在执行更昂贵的长度和按字符检查之前,字符串可能是相同的引用并且在这种情况下完成得非常快。使用这种方法总是更好。在 java 的未来版本中,处理字符串的方式可能会改变,也可能不会改变。使用 equals 方法是安全的。

你不能像字符串那样只比较字符串数组和 ==。 Intern 仅适用于字符串。如果你想比较字符串数组试试这个 Java, how to compare Strings with String Arrays