快速业务通道

Java:所有的equals方法实现都是错误的? - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-21
 // 输出 true

此处的集合不包含 p,但 p 却在该集合的元素之中!发生了什么事呢?在更改 x 域之后,点 p 最后被放在了该集合 coll 下错误的散列桶中。也就是,其初始散列桶与散列码的新值已不再对应。在某种意义上可以说,点 p 在集合 coll 中消失了,即使它仍然是集合中元素。

从这个示例得出的教训就是,当equals和 hashCode 取决于可变状态时,可能会为用户带来问题。如果他们将这种对象放入集合中,必须小心,不要修改决定性的状态。而这是很棘手的。如果你现在需要进行一个比较,要考虑到对象的当前状态,通常不应直接使用 equals,而是使用其他命名。 对于 Point 的上一个定义,更为可取的是省略 hashCode 的重定义,并且命名比较方法 equalContents,或者使用其他不同于equals的命名。 这样,Point 将能够继承equals和 hashCode 的缺省实现。

Java:所有的equals方法实现都是错误的?(5)

时间:2011-01-05 司马牵牛译

陷阱 4:未能成功地将equals定义为等值关系

Object 中equals的约定指出 equals 必须实现非空对象的等值关系:

◆自反性:对于如何非空值 x,表达式 x.equals(x) 应返回true。

◆对称性:对于任何非空值:x 和 y,x.equals(y) 应返回true,当且仅当 y.equals(x) 返回 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。

目前,对于 Point 类所使用的equals定义满足了equals的约定。然而,一旦涉及子类,事情将变得更加复杂。比如说,Point 有一个子类 ColoredPoint,其中添加了一个 Color 类型的域 color。假定将 Color 定义为枚举类型:

public enum Color {   RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET; }

ColoredPoint 改写 equals,并添加新的 color 域:

public class ColoredPoint extends Point { // 问题:equals 不对称   private final Color color;   public ColoredPoint(int x, int y, Color color) {   super(x, y);   this.color = color;   }   @Override public boolean equals(Object other) {   boolean result = false;   if (other instanceof ColoredPoint) {   ColoredPoint that = (ColoredPoint) other;   result = (this.color.equals(that.color) && super.equals(that));   }   return result;   } }

很多程序员都可能这样编写代码。请注意,在这种情况下,类 ColoredPoint 不必改写 hashCode。因为 ColoredPoint 的equals的新定义比 Point 中被改写的定义更为严格(意味着等值的对象更少),hashCode 的约定仍然有效。 如果两个颜色点是相等的,它们必须具有相同的坐标,因此也已保证它们的散列码是相等的。

以类 ColoredPoint 本身为例,equals的定义看起来没问题。但,一旦普通点和颜色点混合着一起时,equals的约定就将被破坏。 例如:

Point p = new Point(1, 2); ColoredPoint cp = new ColoredPoint(1, 2, Color.RED); System.out.println(p.equals(cp)); // 输出 true System.out.println(cp.equals(p)); // 输出 false

相等比较“pequalscp”将调用 p 的equals方法,已在类 Point 中定义。该方法仅考虑两个点的坐标。因此,相等比较输出 true 值。而另一方面,相等比较“cp equals p”调用 cp 的 equals 方法,其中类 ColoredPoint 中已

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号