快速业务通道

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

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-21
于,Point 的上次实现违法了Object 类中定义的hashCode约定:

如果两个对象根据equals(Object) 方法是等值的,那么对两个对象中任何一个调用 hashCode 方法都必须得到相同的整型结果。

事实上,在Java中,通常应同时对 hashCode 和equals进行重定义,这一事实是广为人知的。此外,hashCode 可能仅依赖equals所依赖的域。对于 Point 类,以下将是一个合适的 hashCode 定义:

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());   }   return result;   }   @Override public int hashCode() {   return (41 * (41 + getX()) + getY());   } }

这只是 hashCode 多种可能的实现中的一种。将常量 41 加到一个整型域 x 上,所得结果再乘以素数 41,然后在加上另一个整型域 y。这样就可以提供合理分布的散列码,而运行时间和代码大小也会降低。

在定义与 Point 相似的类时,添加 hashCode 解决了等值的问题。但是,还有其他的问题需要注意。

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

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

陷阱 3 :对equals进行定义时涉及可变域

以下对 Point 类进行一项细微的修改:

public class Point {   private int x;   private int y;   public Point(int x, int y) {   this.x = x;   this.y = y;   }   public int getX() {   return x;   }   public int getY() {   return y;   }   public void setX(int x) {   this.x = x;   }   public void setY(int y) {   this.y = 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());   }   return result;   }   @Override public int hashCode() {   return (41 * (41 + getX()) + getY());   } }

唯一的不同之处是域 x 和 y 不再是 final 类型,同时添加了两个集合方法,允许用户更改 x 和 y 值。现在,equals和 hashCode 方法的定义涉及了这些可变域,因此域更改时它们的结果也将改变。一旦你将点放入集合中,这会带来很奇怪的效果:

Point p = new Point(1, 2); HashSet< Point> coll = new HashSet< Point>(); coll.add(p); System.out.println(coll.contains(p)); // 输出 true

现在,如果更改点 p 中的域,集合还将包含该点吗? 我们来试试下面的代码:

p.setX(p.getX() + 1); System.out.println(coll.contains(p)); // (很可能)输出 false

这看起来很奇怪。p 到哪里去了?如果你对集合的 iterator 是否包含 p 进行测试,会得到各位奇怪的结果:

Iterator< Point> it = coll.iterator(); boolean containedP = false; while (it.hasNext()) {   Point nextP = it.next();   if (nextP.equals(p)) {   containedP = true;   break;   } } System.out.println(containedP);

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