Java:是assertEquals(String,String)可靠吗?


Answers

assertEquals使用equals方法进行比较。 有一个不同的assert, assertSame ,它使用==运算符。

要理解为什么==不应该与字符串一起使用,您需要了解==作用:它执行身份检查。 也就是说, a == b检查ab指向同一个对象 。 它是建立在语言之上的,其行为不能被不同类别所改变。 另一方面, equals方法可以被类重写。 虽然其默认行为(在Object类中)是使用==运算符进行身份检查,但许多类(包括String )都会覆盖它,而不是执行“等同性”检查。 在String的情况下, a.equals(b)不是检查ab指向同一个对象, a.equals(b)检查它们引用的对象是否都包含完全相同字符的字符串。

比喻时间:想象每个String对象都是一张写有东西的纸片。 假设我有两张写有“Foo”的纸,另一张写着“Bar”。 如果我拿出前两张纸并使用==比较它们,它将返回false因为它本质上是要求“这些是同一张纸吗?”。 它甚至不需要看看纸上写的是什么。 我给它两张纸(而不是两张相同的纸)意味着它将返回false 。 但是,如果我使用equals ,那么equals方法将读取两张纸并看到他们说的是相同的东西(“Foo”),所以它会返回true

使Strings混淆的一点是,Java有一个“interning”字符串的概念,并且(有效)自动对代码中的任何字符串进行自动执行。 这意味着如果代码中有两个等效的字符串文字(即使它们在不同的类中),它们实际上都会引用同一个String对象。 这使得==运算符比人们期望的更频繁地返回true

Question

我知道==在比较两个Strings时遇到了一些问题。 看来, String.equals()是一个更好的方法。 那么,我正在做JUnit测试,我的倾向是使用assertEquals(str1, str2) 。 这是一个可靠的方式来断言两个字符串包含相同的内容? 我会使用assertTrue(str1.equals(str2)) ,但是你没有看到失败时预期和实际值的好处。

在相关说明中,是否有人链接到页面或线程,以清楚地解释str1 == str2的问题?




JUnit assertEquals(obj1, obj2)确实调用obj1.equals(obj2)

还有assertSame(obj1, obj2) ,它确实obj1 == obj2 (即,验证obj1obj2引用同一个实例),这就是你想要避免的。

所以你很好。




是的,它一直用于测试。 测试框架很可能使用.equals()进行比较,如这些。

以下是解释“字符串平等错误”的链接。 本质上,Java中的字符串是对象,当您比较对象相等时,通常会根据内存地址进行比较,而不是根据内容进行比较。 因此,即使两个字符串的内容相同,也不会占用相同的地址,因此即使它们在打印时看起来相同,它们也不会正确匹配。

http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/