在我的项目上运行 FindBugs 时,我收到了一些上述错误的实例。

也就是说,我的 equals 重写版本将 RHS 对象转换为与定义重写版本的对象相同的类型。

但是,我不确定是否可以有更好的设计,因为 AFAIK Java 不允许方法参数存在差异,因此不可能为 equals 参数定义任何其他类型。

是我做错了什么,还是 FindBugs 太急切了?

表达这个问题的另一种方式是:如果传递给 equals 的对象与 LHS 的类型不同,正确的行为是什么:这是错误的,还是应该有例外?

例如:

public boolean equals(Object rhs)
{
    MyType rhsMyType = (MyType)rhs; // Should throw exception
    if(this.field1().equals(rhsMyType.field1())... // Or whatever
}
有帮助吗?

解决方案

通常,在实现 equals 时,您可以在强制转换之前检查参数的类是否与实现类相等(或兼容)。像这样的东西:

if (getClass() != obj.getClass())
    return false;
MyObj myObj = (MyObj) obj;

这样做可以防止 FindBugs 警告。

针对评论的旁注:
有些人主张使用 instanceof 代替 getClass 检查类型安全。对此有一个很大的争论,当我注意到你可以检查阶级平等时,我试图不参与其中 或者 兼容性,但我想我无法逃避它。归结为这一点 - 如果你使用 instanceof 您可以支持类的实例与其子类的实例之间的相等性,但是您可能会面临破坏对称契约的风险 equals. 。一般来说我建议不要使用 instanceof 除非你知道你需要它并且你知道你在做什么。欲了解更多信息,请参阅:

其他提示

你可能做这样的事情:

public class Foo {
  // some code

  public void equals(Object o) {
    Foo other = (Foo) o;
    // the real equals code
  }
}

在这个例子中我们假定你是一些有关平等的论点():你是假设它是Foo类型。这需要并非如此!您还可以得到一个String(在这种情况下,你应该几乎可以肯定返回false)。

所以,你的代码应该是这样的:

public void equals(Object o) {
  if (!(o instanceof Foo)) {
    return false;
  }
  Foo other = (Foo) o;
  // the real equals code
}

(或使用由Dave大号提到的更严格的getClass() != o.getClass()

您还可以看看它是这样的:

Integer i = new Integer(42);
String s = "fourtytwo";
boolean b = i.equals(s);

是否有任何理由,此代码应该抛出一个ClassCastException代替正常完成并设定bfalse的?

投掷ClassCastException.equals()的响应不会是明智的。因为哪怕是一个愚蠢的问题(“当然,一个字符串是永远等于一个Foo!”),它仍然是一个有效的具有完全没有答案(“无” == false)。

我建议忽略说FindBugs的警告。在实践中,如果等于被称为一个意外类的一个对象,那么几乎可以肯定的错误,并且要失败的错误快。

例如,如果你有一个“ArrayList的文件”,并呼吁files.contains(“MyFile.txt的”),它会如果你有一个ClassCastException是很好的。相反,Java的只是返回false,它可能需要很长的时间,直到你发现的bug。

我开始等于(对象)实现这样的:

if ((object == null) || !(object instaceof ThisClass)) {
    return false;
}

这也将防止FindBugs的警告,但是当ThisClass的一个子类中正在切换将不会自动地返回false,它也可能被认为是相等的,特别是如果其equals(Object)方法尚未重写。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top