我刚刚遇到了一个由Java引起的问题java.awt.geom.Area#equals(Area)
方法。该问题可以简化为以下单元测试:
@org.junit.Test
public void testEquals() {
java.awt.geom.Area a = new java.awt.geom.Area();
java.awt.geom.Area b = new java.awt.geom.Area();
assertTrue(a.equals(b)); // -> true
java.lang.Object o = b;
assertTrue(a.equals(o)); // -> false
}
经过一番绞尽脑汁和调试后,我终于在 JDK 源代码中看到了equals
中的方法Area
看起来像这样:
public boolean equals(Area other)
请注意,它确实not @Override
正常的equals
方法来自Object
,但只是用更具体的类型重载该方法。因此,上面示例中的两个调用最终调用了不同的实现equals
.
由于这种行为自 Java 1.2 以来就已经存在,因此我认为它不被视为错误。因此,我更有兴趣了解why决定是为了not正确地覆盖equals
方法,但同时提供一个重载变体。 (表明这是一个实际决定的另一个暗示是没有被覆盖hashCode()
方法。)
我唯一的猜测是作者担心缓慢equals
区域的实现不适合在放置时比较平等Area
s in Set
,Map
,ETC。数据结构。 (在上面的示例中,您可以添加a
to a HashSet
,虽然b
等于a
, 呼叫contains(b)
会失败。)话又说回来,为什么他们不只是以一种不与诸如equals
方法 ?
RealSkeptic 链接到JDK-4391558 https://bugs.openjdk.java.net/browse/JDK-4391558在上面的评论中。这该错误解释了原因:
重写 equals(Object) 的问题是你还必须
重写 hashCode() 以返回一个保证 equals() 的值
仅当两个对象的哈希码也相等时才为 true。
but:
这里的问题是 Area.equals(Area) 并没有执行非常好的操作
直接比较。它精心检查每一个
两个区域中的几何图形并测试它们是否覆盖了
相同的封闭空间。两个 Area 对象可以具有完全的
同一封闭空间的不同描述和 equals(Area)
会发现它们是相同的。
所以基本上我们留下了一系列不太令人愉快的选项,例如:
弃用 equals(Area) 并为其创建一个替代名称
操作,例如“areasEqual”,以避免混淆。
不幸的是,旧方法将保留并且可以链接和
会困住很多想要调用 equals(Object) 的人
版本。
or:
弃用 equals(Area) 并将其实现更改为完全相同
equals(Object) 以避免错误时出现语义问题
方法被调用。创建一个具有不同名称的新方法以避免
混淆实现 equals(Area) 提供的旧功能。
or:
实现 equals(Object) 来调用 equals(Area) 并实现一个虚拟对象
hashCode() 遵循退化中的 equals/hashCode 契约
通过返回一个常量的方式。这将使 hashCode 方法
本质上毫无用处,并且使 Area 对象作为键中的键几乎毫无用处
HashMap 或哈希表。
或其他方式修改equals(Area)
会改变其语义或使其与hashCode
.
看起来维护者认为更改此方法既不可行(因为错误注释中概述的选项都不能完全解决问题)也不重要(因为实现的方法非常慢,并且可能只会在比较时返回 true一个实例Area
正如评论者所建议的那样)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)