当前位置:  开发笔记 > 编程语言 > 正文

Findbugs警告:Equals方法不应该假设其参数的类型

如何解决《Findbugs警告:Equals方法不应该假设其参数的类型》经验,为你挑选了2个好方法。

在我的项目上运行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
}

Dave L... 36

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

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

这样做会阻止FindBugs警告.

解决评论的旁注:
有些人主张使用instanceof而不是getClass检查类型安全性.关于这一点存在很大争议,当我注意到你可以检查类的相等性兼容性时,我试图不进入这个问题,但我想我无法逃脱它.它归结为这个 - 如果你使用instanceof你可以支持类的实例和它的子类的实例之间的相等,但你冒着破坏对称契约的风险equals.一般来说,我建议不要使用,instanceof除非你知道你需要它,你知道你在做什么.有关更多信息,请参阅

http://www.artima.com/weblogs/viewpost.jsp?thread=4744

在Java中覆盖equals和hashCode时应该考虑哪些问题?

http://www.macchiato.com/columns/Durable5.html

http://commons.apache.org/lang/api-release/org/apache/commons/lang/builder/EqualsBuilder.html(Apache common的实现助手)

http://www.eclipsezone.com/eclipse/forums/t92613.rhtml(Eclipse的默认等于生成器)

NetBeans生成器也使用getClass()

基本上这意味着:不是抛出ClassCastException,而是equals()方法应该返回false. (4认同)

尽管此代码解决了原始的FindBugs问题,但似乎导致FindBugs现在使用NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT标记该代码。因此,您可能需要添加一个空检查,例如:if(obj2 == null || getClass()!= obj2.getClass())` (2认同)


Joachim Saue.. 7

你可能正在做这样的事情:

public class Foo {
  // some code

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

在这个例子中,你假设有关于equals()的参数:你假设它是Foo类型.不一定是这种情况!你也可以得到一个String(在这种情况下你几乎肯定会返回false).

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

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

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

你也可以这样看待它:

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

有没有理由这个代码应该抛出ClassCastException而不是正常完成并设置bfalse

抛出一个ClassCastException回应.equals()是不明智的.因为即使它是一个愚蠢的问题("当然一个字符串永远不会等于一个Foo!")它仍然是一个有效的答案("没有"== false).



1> Dave L...:

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

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

这样做会阻止FindBugs警告.

解决评论的旁注:
有些人主张使用instanceof而不是getClass检查类型安全性.关于这一点存在很大争议,当我注意到你可以检查类的相等性兼容性时,我试图不进入这个问题,但我想我无法逃脱它.它归结为这个 - 如果你使用instanceof你可以支持类的实例和它的子类的实例之间的相等,但你冒着破坏对称契约的风险equals.一般来说,我建议不要使用,instanceof除非你知道你需要它,你知道你在做什么.有关更多信息,请参阅

http://www.artima.com/weblogs/viewpost.jsp?thread=4744

在Java中覆盖equals和hashCode时应该考虑哪些问题?

http://www.macchiato.com/columns/Durable5.html

http://commons.apache.org/lang/api-release/org/apache/commons/lang/builder/EqualsBuilder.html(Apache common的实现助手)

http://www.eclipsezone.com/eclipse/forums/t92613.rhtml(Eclipse的默认等于生成器)

NetBeans生成器也使用getClass()


基本上这意味着:不是抛出ClassCastException,而是equals()方法应该返回false.
尽管此代码解决了原始的FindBugs问题,但似乎导致FindBugs现在使用NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT标记该代码。因此,您可能需要添加一个空检查,例如:if(obj2 == null || getClass()!= obj2.getClass())`

2> Joachim Saue..:

你可能正在做这样的事情:

public class Foo {
  // some code

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

在这个例子中,你假设有关于equals()的参数:你假设它是Foo类型.不一定是这种情况!你也可以得到一个String(在这种情况下你几乎肯定会返回false).

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

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

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

你也可以这样看待它:

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

有没有理由这个代码应该抛出ClassCastException而不是正常完成并设置bfalse

抛出一个ClassCastException回应.equals()是不明智的.因为即使它是一个愚蠢的问题("当然一个字符串永远不会等于一个Foo!")它仍然是一个有效的答案("没有"== false).

推荐阅读
无名有名我无名_593
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有