为什么Java的String#replace()方法对字符和字符串的工作方式不同?

时间:2012-09-28 19:09:31

标签: java string

为什么以下表达式评估为false

aStr.replace("H", "H") == "Hello"

虽然这个替代表达式的评估结果是真的吗?

aStr.replace('H', 'H') == "Hello"

4 个答案:

答案 0 :(得分:4)

Java在字符串池中缓存String字面值,因此如果String中没有更改,则会从池中获取不可变实例,因此两者都引用内存中的相同实例,因此{{1引用返回==

因此,要比较字符串对象,您应该使用true方法/ equals()方法


另见

答案 1 :(得分:2)

应使用.equals()

进行字符串比较

如果比较是在字符串文字之间,则==比较可能有效,因为文字被缓存在池中并引用相同的变量。

equals()比较值,==比较参考。

答案 2 :(得分:2)

String类的replace(char, char)方法会扫描以查找匹配的字符。如果找不到,则返回主机String实例。当然,通过==运算符将返回的引用与原始引用进行比较会返回true,因为它正在测试引用相等,并且这两个引用是同一个。

但是,如果原始字符串包含&#39; H&#39;字符 - 在这里使用你的例子 - 然后返回的字符串将与原始字符串相同(即使它将是相同的逐个字符);它将是一个新分配的实例,它将无法通过引用相等性进行比较(同样,==运算符)。将返回的String与原始的Object#equals()进行比较将返回true,因为两个字符串等效,但它们将是通过引用相等而无法匹配的不同实例。< / p>

相比之下,String#replace(CharSequence, CharSequence)将目标字符串视为正则表达式;它在内部使用Matcher#replaceAll()来替换目标模式中的匹配项,并使用提供的替换序列。

现在问题归结为Matcher#replaceAll()是否会返回原始字符串或新分配的副本,即使模式不匹配也是如此。通过阅读Oracle库中的代码,如果Matcher找不到匹配的模式,则会在原CharSequence#toString()上返回CharSequenceStringthis 1}}对象只返回未调整的String引用。这让我想知道你是否在这里报告了真实的结果。

提出的问题中一个明显的漏洞是aStr引用的final String aStr = "Hello"; 的原始内容。你可能想要显示一个像

这样的声明
aStr

但你没有。这两个表达式的结果应取决于String#replace()是否包含&#39; H&#39;性格与否。假设确实如此,我认为两个表达式都会产生错误,假设任何String#replace()重载都没有string interning。我们知道字符串文字是实习的,但是我们在Oracle库的两个{{1}}方法的实现中构建的返回值是新分配的,而不是从实习池中提取的。

答案 3 :(得分:0)

使用String.equals()来比较字符串。

        System.out.println((aStr.replace("H","H").equals("Hello")));

将返回 true