有什么可以警告我反对type.equals(incompatibleType)吗?

时间:2011-10-26 02:58:48

标签: java equals static-analysis

是否有任何工具可以警告我不要使用以下类型的代码:

if ( someClass.equals( someString ))

例如:

if ( myObject.getClass().equals( myClassName ))

这样的事情是合法的Java(equals接受一个Object)但永远不会评估为true(一个类永远不能等于一个String)所以几乎肯定是一个bug。

我检查过Eclipse,FindBugs和PMD,但似乎没有人支持此功能?

3 个答案:

答案 0 :(得分:8)

是的, IntelliJ IDEA 进行了这样的检查,我相信默认情况下已启用。它标记以下内容:

Class<?> clazz = String.class;
if (clazz.equals("foo")) {
   //...
}

警告:

  不可逆类型的对象之间的

'等于()'。

可以通过设置 - &gt;项目设置 - &gt;检查启用/禁用检查,然后在可能的错误下检查/取消选中“不可转换类型的对象之间的''等于()”。“

FindBugs 也应该通过"EC: Call to equals() comparing different types"错误检查来识别它。它可以与Eclipse集成,因为您可能已经知道了。

虽然也没有银弹;他们无法读懂你的想法。你可以期待的最好的是它会有利于误报,而不是假阴性。

答案 1 :(得分:1)

您要检查的内容不一定是“问题”:equals()类中声明了Object,并将Object作为参数。类覆盖这个方法,它们的实现可能允许不同类的对象“等于”目标对象。

我自己已经做了几次,例如,如果另一个对象(比如String)与目标的键字段匹配,则允许对象“等于”另一个对象:

class MyClass {
    private String id;

    public boolean equals(Object obj) {
        // Compare as if "this" is the id field
        return id.equals(obj instanceof MyClass ? ((MyClass)obj).id : obj);
    }

    public int hashCode() {
        return id.hashCode(); // so hashCode() agrees with equals()
    }
}

它实际上非常方便,因为以下代码将按预期工作:

List<MyClass> list = new ArrayList<MyClass>();
// collection methods will work with instances:
list.contains(someInstance);
list.remove(someInstance);
list.indexOf(someInstance);
// and with keys!
// handy if you can only get the key, for example from a web url parameter
list.contains("somekey");
list.remove("somekey");
list.indexOf("somekey");

答案 2 :(得分:1)

这是.NET中IEquatable<T>接口背后的想法:为类型提供一种机制来实现我称之为强类型的相等性。还有IEqualityComparer<T>接口,允许以单独的类型实现此逻辑。

根据this StackOverflow question(Jon Skeet的回答,他通常似乎知道他在说什么),在Java中似乎没有任何等价物。

当然,你总是可以自己为自己的类型实现这样的东西,但是对于作为Java基类库一部分的类型,它不会对你有很大帮助。对于此类问题的编译时检测,最好的选择是某种分析工具(Mark Peters indicates显然有一个内置于IntelliJ IDEA中)可以向您建议某些代码可能要怀疑。一般来说,假设你不是一个不理会警告的人,这应该足够好了。