在我的项目上运行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
而不是正常完成并设置b
为false
?
抛出一个ClassCastException
回应.equals()
是不明智的.因为即使它是一个愚蠢的问题("当然一个字符串永远不会等于一个Foo!")它仍然是一个有效的答案("没有"== false
).
通常,在实现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()
你可能正在做这样的事情:
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
而不是正常完成并设置b
为false
?
抛出一个ClassCastException
回应.equals()
是不明智的.因为即使它是一个愚蠢的问题("当然一个字符串永远不会等于一个Foo!")它仍然是一个有效的答案("没有"== false
).