繁体   English   中英

为什么(不是如何)Object必须符合equals()的javadoc?

[英]Why (not how) must an Object conform to the javadoc of equals()?

Object.equals()的javadoc解释了正确覆盖该方法所需遵循的规则。 它说:

  1. 它是自反的:对于任何非空引用值x,x.equals(x)应该返回true。
  2. 它是对称的:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true。
  3. 它是传递性的:对于任何非空引用值x,y和z,如果x.equals(y)返回true而y.equals(z)返回true,则x.equals(z)应返回true。
  4. 它是一致的:对于任何非空引用值x和y,x.equals(y)的多次调用始终返回true或始终返回false,前提是不修改在对象的equals比较中使用的信息。
  5. 对于任何非空引用值x,x.equals(null)应返回false。

如果有人问我为什么equals()应遵循这些规则,我能给出的唯一答案是“因为javadoc这么说”。 我对此并不满意。 我想更深入地了解为什么存在这些规则。 有人可以通过这些规则并解释一下,如果违反这些规则会出现什么问题吗?

这些是平等如何运作的数学定义。 我会将数学称为更深层次的原因。

Collections API的设计者Joshua Bloch在他的“Effective Java”中拼写了这些内容。 我建议您阅读该章和所有其他章节。

你可以在这里找到第3章。

主要原因是有许多类和API依赖于equals的正确功能才能正常工作。 最常见的用途是java.util包, List s和Set s以及Map s等,但还有很多很多其他的。

通过对equals进行强大的定义,您可以为排序等功能启用功能。而不是给您一个“理由”,这很难做到,我将为您提供一个示例。

  • 自反:如果你试图将相同的元素放在一个Set两次,它将在set中两次,防止无重复功能工作。
  • 对称:排序功能非常难以预测。
  • 传递:再次,排序功能。
  • 一致:一切都将是可悲的不可预测的。
  • 空:插入对于诸如Set s和Map s之类的东西没什么意义

有关更多信息,我邀请您查看有关EqualityWikipedia条目

需求

它是自反的:对于任何非空引用值x,x.equals(x)应该返回true。

说明

这就是说,与自身相比,对象X应始终返回true。 逻辑上如下。 想想'='运算符。

int x = 1;
int y = 1;
if(x == x) { // We expect this to be true every time }


需求

它是对称的:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true。

说明

嗯,这是数学中的=的属性。 看看它是这样的:

 int x = 1; int y = 1; if(x == y) { // This should return true } if(y == x) { // We expect this to have the same output as the first if } 


需求

它是传递性的:对于任何非空引用值x,y和z,如果x.equals(y)返回true而y.equals(z)返回true,则x.equals(z)应返回true。

说明

同样,一些代码可以解释原因。

 int x = 1; int y = 1; int z = 1; if(y == x && x == z) { // It only logically follows that y == z. } 


需求

它是一致的:对于任何非空引用值x和y,x.equals(y)的多次调用始终返回true或始终返回false,前提是不修改在对象的equals比较中使用的信息。

说明

这个是一种自我解释。 它所说的就是它的行为就像一个数学函数。 也就是说,对于相同的输入,它每次都会产生相同的输出。


需求

对于任何非空引用值x,x.equals(null)应返回false。

说明

这只是一个商定的标准。 而且,逻辑上也是如此。 要成功调用对象的equals方法,它必须non-null 如果它non-null ,并且您正在测试与null相等性,那么它必须是不相等的,因此是false

如果您在哲学上要求我们为什么应该遵循API的给定虚拟方法的任何规则,答案是每个软件都注定要存在于一个庞大的生态系统中 ,如果为某些软件定义了一些指导方针,那么它就更实用了。该生态系统内的互动。 如果不是这样,我们将面临兼容性,维护和进步的噩梦。

如果你的问题确实特定于equals()方法而没有别的,那么......这个方法的覆盖所需的大多数属性都源于我们如何在数学和逻辑中使用相等性 我不能指出这个属性不适用的有用系统。 所以,原因是熟悉和可预测性。

它是自反的:对于任何非空引用值x,x.equals(x)应该返回true。

这几乎是equals()方法的本质 如果这不适用,该方法将没有目的 - 或者至少它应该有另一个名称。

它是对称的:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true。

如果x equals y不是y equals x的等价语句,我们必须偏离一种非常熟悉且根深蒂固的思维方式来用Java编程。 无论顺序如何, 这两个表达式都应该进行相同的检查 ,否则它们不表示真正的相等,而是表示其他的(某种程度上的部分相等)。

它是传递性的:对于任何非空引用值x,y和z,如果x.equals(y)返回true而y.equals(z)返回true,则x.equals(z)应返回true。

如果不是这样,那就意味着equals()不仅仅是以确定的方式比较两个对象的状态。 也许它涉及非确定性行为,或者它可能会考虑另一个对象状态或比较中的程序状态 ,这会使它变得非常不可预测并且比它更有用。

它是一致的:对于任何非空引用值x和y,x.equals(y)的多次调用始终返回true或始终返回false,前提是不修改在对象的equals比较中使用的信息。

如果这不是真的,那就意味着equals() (根据不符合上述的定义)涉及一些非确定性的东西。 我没有理由想到为什么人们会在比较中想要非确定性的行为。

对于任何非空引用值x,x.equals(null)应返回false。

这是一种直观有意义的惯例 将对象与null比较经常发生,因此这种情况具有对该场合最有用的行为。 如果我们无法将活动对象与null分开来,我们必须最终得到一些非常笨拙的代码模式。

暂无
暂无

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

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