重写正确的Java等于方法
我重写了Java类中的equals()
方法,发现了一个我无法解释的难题。
标准equals()
合同规定了这一点:
因此,标准的equals()
方法可以这样构造:
public boolean equals(Object other) {
if (null == other) return false;
if (this == other) return true;
if (!(other instanceof MyClassName)) return false;
MyClassName that = (MyClassName) other;
return this.myMemberVariable.equals(that.name);
}
给定类Foo
和类Bar extends Foo
,都使用成员变量String baz
, Foo
内的标准equals()
方法看起来像:
public boolean equals(Object other) {
if (null == other) return false;
if (this == other) return true;
if (!(other instanceof Foo)) return false;
Foo that = (Foo) other;
return this.baz.equals(that.name);
}
Bar
内的标准equals()
方法看起来像这样:
public boolean equals(Object other) {
if (null == other) return false;
if (this == other) return true;
if (!(other instanceof Bar)) return false;
Barthat = (Bar) other;
return this.baz.equals(that.name);
}
如果我有对象Foo foo = new Foo("Test");
和Bar bar = new Bar("Test");
,并且我调用了foo.equals(bar)
,这将返回true
。 如果我通过equals()
合约的对称子句调用bar.equals(foo)
,这是因为在Bar
equals()
中, (!(other instanceof Bar))
是true
,所以Bar
的equal()
方法返回false
,这是不正确的,它应该是true
,通过逻辑(两个对象String baz
是彼此相等的),并通过对称子句,其中如果x.equals(y)
, y.equals(x)
本质上是true
。
我知道用于重写equals()
的getClass()
vs instanceof
参数,并且不需要这些参数中的另一个参数。
这让我想起了我的实际问题。 在这种情况下,如何正确地重写遵循标准Java合约的equals()
方法以实现相等性?
根据你的问题
baz
Foo
可以等于Bar
baz
Foo
可以等于Foo
baz
Bar
可以等于Bar
这清楚地表明Foo
和Bar
将具有与equals()
完全相同的实现。 因此,你不应该重写它。
如果您试图无视这一点并覆盖它,那么您会得出一个明显的结论:您无法将Bar
下降到Foo
,但您可以将这两个参数都投射到Bar
。 只要你做到这一点,你会发现你可以简单使用.equals()
从Bar
。
上一篇: Overriding Proper Java equals method
下一篇: compareTo triggered at first add call on TreeSet in Java 1.7