快速业务通道

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

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-21
{   return (other instanceof Point);   } }

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

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

类 Point:该版本的equals方法包含了一个附加的要求,由 canEqual 方法决定,其他(other)对象可以等于这个(this)对象。Point 中的 canEqual 实现声明所有 Point 实例都可以是相等的。

下面是 ColoredPoint 相应的实现:

public class ColoredPoint extends Point { // 不再违反对称性要求   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 = (that.canEqual(this) && this.color.equals(that.color) && super.equals(that));   }   return result;   }   @Override public int hashCode() {   return (41 * super.hashCode() + color.hashCode());   }   @Override public boolean canEqual(Object other) {   return (other instanceof ColoredPoint);   } }

可以证明 Point 和 ColoredPoint 的新定义满足了equals的约定。 等值是对称和可传递的。将一个 Point 与 ColoredPoint 比较,总会输出 false。事实上,任何普通点 p 和颜色点 cp,“p.equals(cp)”将返回 false ,因为“cp.canEqual(p)”将返回 false。反向进行比较,“cp.equals(p)”也将返回 false ,因为 p 的确不是ColoredPoint,所以 ColoredPoint 中equals正文中第一个 instanceof 检查将失败。

另一方面, Point 的不同子类的实例可以是相等的,只要这些类没有重定义等值比较方法。例如,使用新的类定义,p 和 pAnon 的比较结果为 true。下面是一些例子:

Point p = new Point(1, 2); ColoredPoint cp = new ColoredPoint(1, 2, Color.INDIGO); Point pAnon = new Point(1, 1) {   @Override public int getY() {   return 2;   } }; Set coll = new java.util.HashSet(); coll.add(p); System.out.println(coll.contains(p)); // 输出 true System.out.println(coll.contains(cp)); // 输出 false System.out.println(coll.contains(pAnon)); // 输出 true

这些例子显示,如果超类equals实现定义并调用 canEqual,那么实现子类的程序员可以决定他们的子类是否与超类的实例相等。由于 ColoredPoint 改写了 canEqual,例如,颜色点可能远不会与普通点相等。但由于 pAnon 中引用的匿名子类并未改写 canEqual,其实例可以与 Point 实例相等。

对 canEqual 方式,一种可能的批评是,它违反了里氏替换原则(Liskov Substitution Principle:缩写 LSP)。例如,通过比较运行时类来实现 equals 的技巧,被认为违反了 LSP,因为该技巧导致无法定义这样一个子类:其实例可以等于超类的实例。其推理思路是,LSP 声明:在需要超类实例的地方,你应能够使用(调换)子类实例。但是,在之前的实例中,“coll.contains(cp)”返回 false,即使 cp 的 x 和 y 值与集合中点相匹配。因此,看起来它可能像是违反了 LSP,因为你不能中出现 Point 的地方使用 ColoredPoint。但是,我们认为这是一种错误的解释,因为 LSP 并不要求子类的行为与超类完全相同,而只是它的行为方式能够满足超类的约定。

编写equals方法对运行时类进行比较的问题不在于它违反了 LSP,而是它没有为你提

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站: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号