(当然,除非您确实重写了Object.equals()
)。
我偶然发现了用户Frank的一个非常奇怪的Stack Overflow问题 :
为什么Java的Area#equals方法不能覆盖Object#equals?
有趣的是,有一个Area.equals(Area)
方法实际上采用Area
参数,而不是Object.equals()
声明的Object
参数。 弗兰克(Frank)发现,这会导致令人讨厌的行为:
@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)); // -> truejava.lang.Object o = b;assertTrue(a.equals(o)); // -> false
}
从技术上讲,以这种方式实现AWT的Area是正确的(因为也没有实现hashCode()
),但是Java解析方法的方式以及程序员摘要已像上述代码一样编写的代码的方式是重载equals方法确实是一个可怕的主意。
也没有静态等于
这些规则也适用于静态equals()
方法,例如Apache Commons Lang的
ObjectUtils.equals(Object o1, Object o2)
由于您无法静态导入此equals方法,因此造成了混乱:
import static org.apache.commons.lang.ObjectUtils.equals;
现在,输入以下内容:
equals(obj1, obj2);
您将得到一个编译器错误:
Object类型中的equals(Object)方法不适用于参数(…,…)
这样做的原因是,在当前类及其父类型范围内的方法将始终隐藏以这种方式导入的任何内容。 以下内容也不起作用:
import static org.apache.commons.lang.ObjectUtils.defaultIfNull;public class Test {void test() {defaultIfNull(null, null);// ^^ compilation error here}void defaultIfNull() {}
}
此堆栈溢出问题中的详细信息 。
结论
结论很简单。 永远不要重载Object
声明的任何方法 (当然可以重写)。 这包括:
-
clone()
-
equals()
-
finalize()
-
getClass()
-
hashCode()
-
notify()
-
notifyAll()
-
toString()
-
wait()
当然,如果不首先在Object
中声明这些方法,那将是很棒的事情,但是那艘船已经航行了20年。
翻译自: https://www.javacodegeeks.com/2015/02/thou-shalt-not-name-thy-method-equals.html