快速业务通道

如何在Java中避免equals方法的隐藏陷阱 - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-21
t;(); hashSet1.add(p); System.out.println(hashSet1.contains(cp));    // 打印 false Set<Point> hashSet2 = new java.util.HashSet<Point>(); hashSet2.add(cp); System.out.println(hashSet2.contains(p));    // 打印 true

因此虽然p和cp是等价的,但是contains测试中一个返回成功,另外一个却返回失败。

你如何修改equals的定义,才能使得这个方法满足对称性?本质上说有两种方法,你可以使得这种关系变得更一般化或更严格。更一般化的意思是这一对对象,a和b,被用于进行对比,无论是a比b还是b比a 都返回true,下面是代码:

public class ColoredPoint extends Point { // Problem: equals not transitive 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)); } else if (other instanceof Point) { Point that = (Point) other; result = that.equals(this); } return result; } }

如何在Java中避免equals方法的隐藏陷阱(6)

时间:2011-01-04 blogjava 赵锟译

在ColoredPoint中的equals的新定义比老定义中检查了更多的情况:如果对象是一个Point对象而不是ColoredPoint,方法就转变为Point类的equals方法调用。这个所希望达到的效果就是equals的对称性,不管”cp.equals(p)”还是”p.equals(cp)”的结果都是true。然而这种方法,equals的规范还是被破坏了,现在的问题是这个新等价性不满足传递性。考虑下面的一段代码实例,定义了一个点和这个点上上两种不同颜色点:

ColoredPoint redP = new ColoredPoint(1, 2, Color.RED); ColoredPoint blueP = new ColoredPoint(1, 2, Color.BLUE);

redP等价于p,p等价于blueP

System.out.println(redP.equals(p)); // prints true System.out.println(p.equals(blueP)); // prints true

然而,对比redP和blueP的结果是false:

System.out.println(redP.equals(blueP)); // 打印 false

因此,equals的传递性就被违背了。

使equals的关系更一般化似乎会将我们带入到死胡同。我们应该采用更严格化的方法。一种更严格化的equals方法是认为不同类的对象是不同的。这个可以通过修改Point类和ColoredPoint类的equals方法来达到。你能增加额外的比较来检查是否运行态的这个Point类和那个Point类是同一个类,就像如下所示的代码一样:

// A technically valid, but unsatisfying, equals method public class Point { private final int x; private final int y; public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } @Override public boolean equals(Object other) { boolean result = false; if (other instanceof Point) { Point that = (Point) other; result = (this.getX() == that.getX() && this.getY() == that.getY() && this.getClass().equals(that.getClass())); } return result; } @Override public int hashCode() { return (41 * (41 + getX()) + getY()); } }

你现在可以将ColoredPoint类的equals实现用回刚才那个不满足对称性要的equals实现了。

public class ColoredPoint extends Point { // 不再违反对称性需求 private final Color color; public ColoredPoint(int x, int y, Color color) { super(x, y); this.c

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