繁体   English   中英

为什么Java编译器不对数组进行实习?

[英]Why java compiler does not interns arrays?

考虑下面的代码

String s1 = "testString";
String s2 = "testString";
if(s1 == s2)System.out.println("equals!");

它输出等于!,(我知道编译器对String进行了interning)

String[] s1 = {"testString","teststring2"};
String[] s2 = {"testString","teststring2"};
if(s1 == s2)System.out.println("equals!");

但是上面的代码不起作用,为什么Java编译器不对字符串数组进行实习?

原因是String是不可变的。 您必须创建新实例才能更改它。 因此,尽可能使用相同的实例来匹配字符串是安全的。 字符串是常量; 它们的值创建后无法更改。

数组有何不同? 您可以更改一个数组,只需将一个新值分配给其中一个字段即可。

s1[0] = "testString3"

如果编译器对s1s2使用相同的实例,则将自动更改两个数组。 那可能不是您想要做的。 这就是为什么数组没有被实习的原因。

另请注意,字符串实习可能会受到限制,具体取决于编译器,并且编译器可能会选择不对某些字符串进行实习,具体取决于存在的字符串数或字符串的长度。 有一个内部字符串表,该表由JVM选项+XX:StringTableSize=n控制,该选项确定用于存储内部字符串的字符串表的大小。

当比较字符串时,最好使用equals函数。 无论如何,大多数实现都会先执行参考相等性检查,然后再执行更昂贵的检查。

编辑:

因此,实际上我声称内部存储字符串已满的说法似乎是错误的。 String.intern()方法的文档表明,此函数将确保将字符串添加到唯一字符串池中。 意味着该池将无法充满。 @Holger写道,内部实现使用类似于某种结构的哈希图。 这支持了这一主张。

因此,JVM将根据JLS§3.10.5将所有常量字符串存储在内部哈希表中。

字符串文字始终引用类String的相同实例。 这是因为使用String.intern方法,对字符串文字(或更广泛地说,是常量表达式值…的字符串)进行了“ interned”,以便共享唯一的实例。

话虽如此,请仍然习惯于字符串类的equals方法来检查字符串是否相等。 该方法将利用以下事实:在执行更昂贵的长度和字符检查之前,字符串可能是相同的引用,并且在这种情况下非常快速地完成。 始终最好使用此方法。 在将来的Java版本中,如何处理字符串的方式可能会也可能不会改变。 使用equals方法,您会很安全。

您不能仅将String数组与==进行比较,例如String。 实习生仅适用于String。 如果要比较字符串数组,请尝试使用此Java,如何比较字符串和字符串数组

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM