当前位置: 动力学知识库 > 问答 > 编程问答 >

java - Can anything warn me against type.equals(incompatibleType)?

问题描述:

Is there any tool that can warn me against the following sort of code:

if ( someClass.equals( someString ))

For example:

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

Such a thing is legal Java (equals takes an Object) but will never evaluate to true (a class can never equal a String) so is almost certainly a bug.

I have checked Eclipse, FindBugs and PMD but none seem to support this feature?

网友答案:

Yes, IntelliJ IDEA has such an inspection that I believe is enabled by default. It flags the following:

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

With the warning:

'equals()' between objects of inconvertible types.

The inspection can be enabled/disabled through Settings->Project Settings->Inspections, then under Probable Bugs check/uncheck "'equals()' between objects of inconvertible types."

FindBugs also should catch this with the "EC: Call to equals() comparing different types" bug check. It can be integrated with Eclipse as it appears you are aware.

Neither is a silver bullet though; they can't read your mind. The best you can hope for is that it will favour false positives rather than false negatives.

网友答案:

This is the idea behind the IEquatable<T> interface in .NET: providing a mechanism for types to implement what I'll call strongly typed equality. There is also the IEqualityComparer<T> interface for allowing this logic to be implemented in a separate type.

According to this StackOverflow question (answered by Jon Skeet, who generally seems to know what he's talking about), there doesn't seem to be any equivalent in Java.

Of course, you can always implement such a thing yourself for your own types, but it won't do you much good with types that are part of Java's base class libraries. For compile-time detection of such issues, your best bet is some sort of analysis tool (Mark Peters indicates there is apparently one built in to IntelliJ IDEA) that can suggest to you that certain code might be suspect. In general, assuming you aren't one to ignore warnings, this ought to be good enough.

网友答案:

What you are checking for is not necessarily a "problem": equals() is declared in the Object class, and takes and Object as its parameter. Classes override this method, and their implementation may well allow an object of a different class to "equal" the target object.

I have done this a few times myself, for example for allowing an object to "equal" another object if the other object (say a String) matches the key field of the target:

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()
    }
}

It's actually pretty handy, because the following code will work as desired:

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");
分享给朋友:
您可能感兴趣的文章:
随机阅读: