我有一个Point
类和一个MinesweeperSquare
类,后者是前者的子类。如果我覆盖后者中的equals
方法,就像这样:
if (!(obj instanceof MinesweeperSquare)) {
return false;
}
FindBugs报告:
此类定义一个equals方法,该方法覆盖超类中的equals方法。两者都等于方法 方法使用
instanceof
来确定两个对象是否相等。这充满了危险, 因为重要的是equals方法是对称的(换句话说,a.equals(b) == b.equals(a)
)。 如果B是A的子类型,并且A的equals方法检查参数是A的实例,B的等于方法 检查参数是B的实例,很可能是由这些定义的等价关系 方法不对称。
在Point
课程中,我写道:
if (!(obj instanceof Point)) {
return false;
}
如何在equals
中编写MinesweeperSquare
方法,使equals
方法对称?
更新
如果我在MinesweeperSquare
中写下以下内容,则FindBugs报告没有错误:
if (o == null || this.getClass() != o.getClass()) {
return false;
}
答案 0 :(得分:3)
在您的新方法中,MinesweeperSquare.equals(Point)
将始终返回false,但Point.equals(MinesweeperSquare)
可能会返回true
。在这种事情上使用FindBugs对你很好。您可以在getClass()
和Point
的定义中使用MinesweeperSquare
来检查类是否完全相同......尽管这也很棘手。
答案 1 :(得分:1)
正如您已经引用过的,如果在equals()方法实现中使用'instanceof'运算符,它将变为非对称运算符。摆脱超类中的'instanceof'以及所有子类,并尝试根据类属性和常识覆盖equals()方法。大多数IDE允许您自动生成equals()方法,这是一个很好的起点。
答案 2 :(得分:1)
如果正确完成,使用instanceof
就没问题,如果没有正确的讲座,这很难。使用
this.getClass().equals(that.getClass())
是微不足道的,但并不总能满足您的需求。查看canEqual
的{{3}}。
这一切都只适用于你控制这两个类的情况,这在这里似乎并非如此。所以坚持使用简单的方法。