Java:所有的equals方法实现都是错误的? - 编程入门网
因将清晰可见。将 p2a 定义为 p2 的别名,但使用的是 Object 类型而不是 Point:
现在,如果你重复第一个比较,使用别名 p2a 而不是 p2,结果是:
哪里出错了呢?事实上,由于类型不同,之前指定的 equals 版本并没有改写标准方法 equals。下面是在根类 Object 中定义的 equals 方法:
由于 Point 中的 equals 方法使用 Point 而不是 Object 作为参数,因此,它并未对 Object 中的 equals 进行改写。相反,它只是一种重载的替代方法。Java 中重载由参数的静态类型解析,而不是运行时(run-time)类型。因此,只要参数的静态类型是 Point,就调用 Point 中的 equals 方法。同样,如果静态参数是 Object 类型,就调用 Object 中的 equals 方法。该方法没有被改写,因此在对 object 参数进行比较时,仍使用该方法。这就是“p1.equals(p2a)”输出 false 的原因,即使点 p1 和 p2a 具有相同的 x 和 y 值。这也是为什么在 HashSet 中 contains 方法返回 false 的原因。该方法是针对对常规集合进行操作,因此它会调用 Object 中的常规 equals 方法,而不是 Point 中重载的方法变种。 下面的代码定义了一个更好的equals方法:
现在,equals 具有了正确的类型。它将 Object 类型的值作为参数并输出一个 boolean 结果。该方法的实现使用了 instanceof 和 cast(类型转换)。它首先检测其他(other)对象是否为 Point 类型。如果是,它将对这 2 个点的坐标进行比较,然后返回结果。否则,输出为 false。 Java:所有的equals方法实现都是错误的?(3)时间:2011-01-05 司马牵牛译陷阱2 :更改equals而未同时更改hashCode 如果你使用 Point 的最新定义,再次对 p1和 p2a 进行比较,将会得到期望中的结果:true。但是,如果你重复 HashSet.contains 测试,结果仍可能是 false:
事实上,输出结果不是百分百确定。你也可能从测试中得到true值。如果得到的结果是true,你可以试试另外一些坐标为1和2的点。最终,你将会找到一个未包含在集合中的点。这里出现错误的原因是,Point重定义了equals而没有对hashCode进行重定义。 请注意,上述实例中的集合为HashSet。这表示,集合中元素被放在由相应的散列码决定的哈希桶(hash bucket)中。在contains测试中,它首先查找散列桶,然后对哈希桶中的所有元素和指定元素进行比较。现在,Point类的最新版本确实对equals进行了重定义,但它没有同时对hashCode进行重定义。所以 hashCode 仍然保持 Object 类中其版本的值:分配对象地址的某种变化格式。p1 和 p2 的散列码几乎肯定是不同,即使这两个点的域(field)是相同的。不同的散列码意味着集合中散列桶具有较高概率的非重复性。contains 测试将根据 p2 的散列码在相应的散列桶中查找匹配的元素。大多数情况下,点 p1 会位于另一个散列桶中,因此绝不会找到它。p1 和 p2 有可能很偶然地位于同一散列桶中。对于这种情况,测试将返回ture 值。 问题在 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |