关于oop:覆盖正确的Java等于方法

Overriding Proper Java equals method

我在Java类中重写了EDCOX1 0的方法,发现了一个我无法解释的难题。

标准equals()合同规定:

  • 它是自反的:对于任何引用值x,x.equals(x)都应返回true。
  • 它是对称的:对于任何引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)应返回true。
  • 它是可传递的:对于任何引用值x、y和z,如果x.equals(y)返回真,y.equals(z)返回真,则x.equals(z)应返回真。
  • 它是一致的:对于任何引用值x和y,多次调用x.equals(y)始终返回true或一致返回false,前提是不修改对象的equals比较中使用的信息。
  • 对于任何非空引用值x,x.equals(null)应返回false。

因此,标准equals()方法的构造如下:

1
2
3
4
5
6
7
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 bazFoo内的标准equals()方法如下:

1
2
3
4
5
6
7
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()方法如下:

1
2
3
4
5
6
7
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。如果我叫bar.equals(foo)的话,根据equals()合同的对称条款,这是因为在Barequals()中,(!(other instanceof Bar))true中,使Barequal()方法返回false中,不正确的,应该是true中,逻辑上(两个对象String baz都等于eacx1〔5〕等于eacx1〔13〕中,使Barequal()方法返回EDOCX11〔22〕中,不正确的,按逻辑(两个对象String baz都等于eacx1〔5〕等于eacx1〔5〕等于eacx1〔13〕中,这是不正确一个ch other),根据对称性条款,如果x.equals(y)y.equals(x)本质上是true

我知道getClass()instanceof的论点,主张推翻equals(),不想再有这样的论点。

这就引出了我的实际问题。在这种情况下,如何正确覆盖遵循标准JAVA合同的EDCOX1 0方法?


根据你的问题

  • 如果Foobaz相同,则Foo可以等于Bar
  • Foobaz相同时,可以等于Foo
  • Barbaz相同时,可以等于Bar

这清楚地表明,FooBar将具有与equals()完全相同的实现。因此,您根本不应该覆盖它。

如果你试图忽略这一点,并且无论如何都要覆盖它,你会得出一个明显的结论:你不能将Bar向下投射到Foo,但是你可以将这两个参数都投射到Bar。一旦你这样做,你就会意识到你可以简单地使用.equals(),从Bar