我遇到了一个由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源代码中看到了Area
类的equals
方法的签名如下:
public boolean equals(Area other)
请注意,它不会覆盖来自Object的普通equals方法,而只是用更具体的类型重载该方法。因此,上面示例中的两个调用最终会调用不同的equals实现。由于这种行为自Java 1.2以来就存在,因此我认为它不被认为是一个错误。因此,我更感兴趣的是找出为什么决定不正确地覆盖equals方法,同时提供重载版本。(另一个暗示这是一个实际决策的迹象是覆盖hashCode()方法的缺失。)
我唯一的猜测是作者担心用于比较面积相等的缓慢的equals实现不适合将Area放入Set、Map等数据结构中进行比较。 (在上面的示例中,你可以将a添加到HashSet中,虽然b等于a,但调用contains(b)将失败。) 然后,他们为什么不只是以不与equals方法这样一个基本概念冲突的方式命名可疑的方法呢?
hashCode
也没有被重写。我认为他们在这里做的只是提供一个“比较”方法,恰好与Object.equals()
同名。个人而言,我会给它取一个不同的名称以避免混淆。 - RealSkeptic