2012-05-11 1145 views
13

我正在使用名为FindBugs的静态分析工具分析以下代码段。将字符串与枚举进行比较

if(str.equals(enum.SOMEVALUE)) {// do something}; 

其中str是一个字符串,enum是一个枚举。该工具会为此代码生成以下警告,并且状态为

此方法在不包含公共子类的不同类类型的两个引用上调用equals(Object)。根据equals()的契约,不同类别的对象应该总是比较不平等;因此,根据java.lang.Object.equals(Object)定义的契约,这种比较的结果在运行时总是为false。

,如果我取代的代码与此上面的行:

if(str.equals(enum.SOMEVALUE.toString())) {// do something}; 

然后警告我disappears.But我不知道,如果该工具生成的警告是真的和我是否修复它正确的方式 ?因为我之前看到过这样的比较,它似乎正常工作。

回答

18

你的第一个比较基本上是错了。您正在比较完全不同类型的对象(StringEnum),并且它们永远不会相等。 甚至在这里给我一个警告。它只是因为equals()接受Object,而不是String

第二个比较是正确

虽然JavaDoc is a bit harsh on name()方法,我真的建议在给定的情况下使用枚举它toString()重写:

if(str.equals(FooEnum.SOMEVALUE.name())) 
+0

非常感谢你的建议,使用的域名(),使我的电流id字段的做法,已经过时类似的情况。 – Bananeweizen

+0

请注意,根据equals(),不同类型的对象肯定是相等的。 FindBugs和IntelliJ都是错误的。在标准的java API中甚至有一个例子:完成List接口的实现通过比较元素来实现equals,即使对于List的不同子类也是如此。 – herman

+0

@herman:你说的对,但是'equals()'必须是* symmetrics *,这很容易用'List'实现完成(它们全部基于'AbstractList'),但不在OP情况下。 –

2

我建议使用:

if (SomeEnum.SOMEVALUE == SomeEnum.valueOf(str)) { 

} 
+2

请注意,如果'str'不代表任何SomeEnum值 –

+0

,这将引发异常,这将有助于在switch语句中使用 –

3

我觉得更换常数toString()可能是正确的做法,但我会将其更改为.name(),因为toString将被重写。

1

据我所知,你是在正确的道路。

if(str.equals(enum.SOMEVALUE.toString())) {// do something}; 

这应该没问题。

3

你可以尝试

enum.SOMEVALUE.name() 

,因为它

返回此枚举常量的名称,正是因为在枚举声明中宣布。