我是否使用Google Guava正确实现了equals和hashCode?

时间:2012-02-13 08:02:00

标签: java equals guava hashcode

我正在使用hibernate并需要覆盖equals和hashCode()。我选择使用google-guava的equals和hashCode助手。

我想知道我在这里遗失了什么。

我已获取/设置 idImage filePath 的方法。

@Entity
@Table(name = "IMAGE")
public class ImageEntity {
    private Integer idImage;
    private String filePath;

    @Override
    public int hashCode() {
        return Objects.hashCode(getFilePath());
    }

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

        if(obj instanceof ImageEntity){
            final ImageEntity otherImage = (ImageEntity) obj;
            return Objects.equal(getFilePath(), otherImage.getFilePath());
        }
        return false;
    }
}

修改

进入继承并获得样本here

3 个答案:

答案 0 :(得分:18)

instanceof运算符的问题在于,如果可以这么说,它会考虑多态性。

例如,假设您执行此操作:

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

然后你这样做:

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

boolean this_will_be_true = ie.equals (advanced_ie);

顾名思义,equals调用将返回true,因为instanceof运算符。

我知道这听起来像是基本的东西,而且大多数人都知道,但是很容易忘记它。现在,如果您想要这种行为,那么没关系,您正确实施了equals。但是如果你认为ImageEntity对象不能等于(假设的)AdvancedImageEntity对象,那么要么ImageEntity声明为final要么忘记instanceof并实现这样的equals方法:

@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;
}

这将检查对象的真实类型,无论引用的类型是什么。如果obj参数是子类的实例,它将“滑动”instanceof。但getClass更加严格,不会允许它。

PS:我不是说instanceof是坏的,不应该使用。我只是说你必须意识到这种特殊情况,并决定是否使用它考虑到这一点。

答案 1 :(得分:12)

您实际上可以使用Guava EqualsTester来测试您的equals和hashCode实现:

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

它在番石榴测试笔中。

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

对您的实施进行细微更改:

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

答案 2 :(得分:3)

它很好。尽管instanceof使得null检查无关紧要。

此外,我认为使用自动生成的ID很好,尽管这是very debatable