Did I implement equals and hashCode correctly using Google Guava?

浪尽此生 提交于 2019-12-04 02:32:25

The problem with the instanceof operator is that it works taking into account polymorphism, if I may say so.

Let's say, for example, that you do this:

public class AdvancedImageEntity extends ImageEntity
{
    //some code here
}

and then you do this:

ImageEntity ie = new ImageEntity ();
AdvancedImageEntity advanced_ie = new AdvancedImageEntity ();

boolean this_will_be_true = ie.equals (advanced_ie);

As the name suggests, that equals call will return true, because of the instanceof operator.

I know this sounds like basic stuff and most people know it, but it's SOOOO damn easy to forget it. Now, if you want that behaviour, then it's fine, you implemented equals correctly. But if you consider that an ImageEntity object must not be equal to an (hypothetical) AdvancedImageEntity object, then either declare ImageEntity to be final OR forget about instanceof and implement your equals method like this:

@Override public boolean equals(final Object obj)
{
    if(obj == this) return true;
    if(obj == null) return false;

    if (getClass ().equals (obj.getClass ()))
    {
        final ImageEntity otherImage = (ImageEntity) obj;

        return Object.equals (getFilePath(), otherImage.getFilePath());
    }

    return false;
}

This will check the object's true type, no matter what type the reference is. If the obj parameter is an instance of a subclass, it would "slip" by instanceof. But getClass is a lot more strict and won't allow it.

PS: I'm not saying that instanceof is bad and should not be used. I'm just saying that you must be aware of this particular situation and decide whether to use it taking this into account.

You could actually use the Guava EqualsTester to test your equals and hashCode implementation:

new EqualsTester()
     .addEqualityGroup("hello", "h" + "ello")
     .addEqualityGroup("world", "wor" + "ld")
     .addEqualityGroup(2, 1 + 1)
     .testEquals();

It's in the guava testlib.

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava-testlib</artifactId>
    <scope>test</scope>
</dependency>

Minor change to your implementation:

@Override public boolean equals(final Object obj) {
    if(obj == this) return true;
    return obj instanceof ImageEntity &&
        Objects.equal(getFilePath(), ((ImageEntity) obj).getFilePath());
}
NimChimpsky

Its fine as is. Although instanceof makes the null check unnessary.

Also, I think its fine to use auto generated id's, although this is very debatable.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!