在标准Java API中,是否存在==
将返回true
的情况,但equals
将返回false
。理论上,这可以写入用户定义的类,而非常像这样
class A {
public boolean equals(Object o) {
return this != o;
}
}
在示例中是否实际出现了某些对象b
和c
,b == c
将返回true
,但b.equals(c)
返回false
}?此外,有这种行为会有任何可能的好处吗?
答案 0 :(得分:5)
没有*。
The contract for equals
has 5 rules,第一个涵盖了这个案例:
equals方法在非null对象引用上实现等价关系:
- 它是自反的:对于任何非空引用值x,x.equals(x)应该返回true。
- 它是对称的:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true。
- 它是传递性的:对于任何非空引用值x,y和z,如果x.equals(y)返回true而y.equals(z)返回true,则x.equals(z)应返回true
- 它是一致的:对于任何非空引用值x和y,x.equals(y)的多次调用始终返回true或始终返回false,前提是没有修改在对象上的equals比较中使用的信息。
- 对于任何非空引用值x,x.equals(null)应返回false。
Java标准库中违反自反性的任何对象都是错误,如果您确实在API中发现了这样的对象,请将其报告给Oracle。
*第三方图书馆可以说较少。开发人员犯错误或不了解equals
合同。通常,这也可以作为第三方库中的错误,但是YMMV。
答案 1 :(得分:1)
在标准Java API中,是否存在
==
将返回true
的情况,但equals
将返回false
[?]
据我所知,并且我相信您发现的任何示例都会被视为错误。
特别是,如果x
和y
是x == y
的引用,则必须是x.equals(y)
评估与x.equals(x)
相同结果的情况}。 Object.equals()
的合同(在其文档中)部分说明了这一点:
equals
方法在非null上实现等价关系 对象引用:
- reflexive :对于任何非空参考值
x
,x.equals(x)
应返回true
。
因此,Object.equals()
的任何覆盖在语义上都是错误的,如果它为任何引用x
和y
生成x == y && !x.equals(y)
为真的结果。
答案 2 :(得分:1)
在标准Java API中,是否存在
==
将返回true
的情况,但equals
将返回false
。
我不确定这是否与您的想法完全相同,但equals
的实现不需要线程安全,并且不需要显式检查参数是否与this
。原则上,foo.equals(foo)
如果false
同时在另一个帖子中进行修改,则foo
可能会返回sb.equals(sb)
。
我怀疑任何JDK类都被明确记录为 not ,包括此检查;相反,这被认为是一个实现细节,除了那是唯一的检查。但是,当ArrayIndexOutOfBoundsException
是sb
时,我已设法让StringBuilder
至少提出false
,另一个线程正在忙于添加元素;所以,如果你的时间特别不吉利,那么它也应该能够返回equals
。
此外,有这种行为会有任何可能的好处吗?
我真的不这么认为。 Set
的全部目的是支持Map
和Assert.assertEquals
以及equals
等内容。有很多用例根本不使用equals
,但我无法想象 使用{{1}的一段非常糟糕的代码但是希望它 not 表示一种被身份所满足的平等形式。
也就是说,对于一个不可怕的代码来说,有一个错误可能会导致错误。例如,我在上面的评论中提到,java.util.Date
和java.sql.Timestamp
存在设计错误(现已正式编纂),其中date.equals(ts)
可以是true
但ts.equals(date)
是false
。尝试解决此类问题的人可能会修改java.util.Date
以包含支票if (that.getClass() == Date.class)
;但是这会导致在任何没有明确覆盖父实现的子类中实现非反身equals
。 (当然,我不会在JDK中遇到这样的错误。)
面对继承正确地编写equals
实际上相当棘手,但幸运的是,有一种已知的解决方案可以用一种简单的方式解决所有复杂问题:http://www.artima.com/lejava/articles/equality.html。
答案 3 :(得分:0)
正如您所指出的,当然可以实现equals
x == x
但!x.equals(x)
。但是,这样做会违反documentated behavior of equals
,它声明此属性必须适用于任何有效的实现。因此,您无法在Java标准API中找到执行此操作的任何示例(除非出现某处的错误),并且您会发现大量代码在equals
上隐式或明确地依赖不这样做。