Java:所有的equals方法实现都是错误的? - 编程入门网
// 输出 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 定义为枚举类型:
ColoredPoint 改写 equals,并添加新的 color 域:
很多程序员都可能这样编写代码。请注意,在这种情况下,类 ColoredPoint 不必改写 hashCode。因为 ColoredPoint 的equals的新定义比 Point 中被改写的定义更为严格(意味着等值的对象更少),hashCode 的约定仍然有效。 如果两个颜色点是相等的,它们必须具有相同的坐标,因此也已保证它们的散列码是相等的。 以类 ColoredPoint 本身为例,equals的定义看起来没问题。但,一旦普通点和颜色点混合着一起时,equals的约定就将被破坏。 例如:
相等比较“pequalscp”将调用 p 的equals方法,已在类 Point 中定义。该方法仅考虑两个点的坐标。因此,相等比较输出 true 值。而另一方面,相等比较“cp equals p”调用 cp 的 equals 方法,其中类 ColoredPoint 中已 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |