Java:所有的equals方法实现都是错误的? - 编程入门网
Java:所有的equals方法实现都是错误的?时间:2011-01-05 司马牵牛译本文介绍了一种改写(override)equals 方法的技巧。使用该技巧,即使在实体类的子类添加了新的域(field)时,仍然能够满足 equals 方法的约定。 在《Effective Java》一书的第 8 条目中,Josh Bloch 将子类化时满足 equals 约定这一困难描述为:面向对象语言中等值关系的最根本问题。Bloch 这样写道: 不存在一种方式,能够在扩展非实例类并添加值组件的同时,仍然满足equals的约定。除非你愿意放弃面向对象的抽象性这一优点。 《Programming in Scala》一书中的第 28 章提供了一种方法,子类可以对非实例类进行扩展,添加值组件,而同时满足 equals 约定。虽然书中提供的那种技巧是用于定义 Scala 类,但一样适用于 Java 中的 类定义。在本文中,为了讲解这种方法,我将使用《Programming in Scala》中相关章节,改编相关的文本,并将原书中的 Scala 示例代码转换为了 Java 代码。 常见的等值陷阱 Class java.lang.Object 定义了一个 equals 方法,其中的子类可以进行改写(override)。不幸的是,最终的结果表明,在面向对象语言中,编写正确的等值方法相当困难。事实上,在对 Java 代码的大量正文进行研究之后,几位作者在 2007 年的一份论文中作出如下结论:几乎所有 equals 方法的实现都是错误的。 这是一个严重的问题,因为等值方法是很多代码的根本。其一,对于类型 C,一个错误的等值方法可能意味着,你不能可靠地将一个类型 C 的对象放入集合中。你可能有两个等值的类型 C 元素 elem1、elem2,即“em1.equals(elem2)”输出 true。然而,在下面的示例中,equals 方法的实现就是一种常见的错误:
存在四种常见的陷阱,它们都会在改写equals时导致非一致性的行为: ◆使用错误的原型对equals进行定义。 ◆更改equals而未同时更改 hashCode。 ◆对equals进行定义时涉及可变域(field)。 ◆未能成功地将equals定义为等值关系。 这四种陷阱将在下文中具体讲述。 陷阱 1:使用错误的原型对equals进行定义 在下面的代码中,我们将为普通点的类添加一个等值方法:
Java:所有的equals方法实现都是错误的?(2)时间:2011-01-05 司马牵牛译一个显而易见的错误定义如下:
这种方法的错误之处是什么?初一看,它可以正常运行:
然而,一旦你将point放入集合中,问题就出来了:
coll 怎么可能不包含 p2 呢?你已经将 p1 添加到其中,而 p1 等于 p2。在下面的互操作中,进行比较的点的具体类型被隐藏,这时,导致问题的原 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |