2014-07-06 64 views
0

所以这是从头部的第一个Java(页563)的hashCode平等对象

的默认行为()是产生堆上每个对象一个唯一的整数 。 因此,如果您不覆盖类中的hashCode(),则不会认为该类型的两个对象相等。

但一个简单的测试将反驳这个我认为。

public class Song { 

    private String name; 

    public Song(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 


    @Override 
    public boolean equals(Object obj) { 
     Song objectSong = (Song) obj; 
     return this.getName().equals(objectSong.getName()); 
    } 

} 

嗯,这将返回true:

Song songA = new Song("A","B"); 
Song songB = new Song("A","C"); 

System.out.println(songA.equals(songB)); 

我这么想吗?这本书试图告诉我什么?

+0

就在你引用它的部分之前说“如果你重写equals(),你必须重写hashCode()”。 – Robert

+0

@Robert对不起,我不明白,你有什么想告诉这个评论? –

+0

在页563上它说:“如果你重写equals(),如果你不重写hashCode(),你必须重写hashCode()”**和**“,没有两个对象可以被认为是相等的。所以如果你不重写hashCode(),你不能覆盖equals(),因此不能认为两个对象是相等的。 – Robert

回答

2

hashCode()的默认行为是生成用于在堆上的每个对象的唯一整数 。因此,如果您不覆盖类中的hashCode(),则不会将这种类型的两个对象视为相等。

你是在误解。作者并不是说一种方法(即所有的equalshashCode)都不能为两个不同的对象返回true。他们说,语义上如果两个对象的hashCode的结果不相等,则不应认为这两个对象相等。他们正在描述如何使用hashCode。如果你以不同的方式使用它,你可能会得到奇怪和意想不到的结果。

+0

+1。例如'HashSet'只考虑*调用匹配散列码的对象的equals。只要散列码不匹配,它们无论如何都不可能相等。 – Robert

1

您需要重写散列码,以便该类的行为与基于散列码的集合(以及其他任何内容)的预期相同。

例如,如果您将您的歌放在HashSet中,然后尝试放入另一个,会发生什么情况?

如果覆盖等于,则应该始终覆盖Hashcode,反之亦然。确保它们一致。

(乔希布洛赫有效的Java,是一个很好的起点)

0

在Java中,每个对象都有访问equals()方法,因为它是 从Object类继承。但是,这个默认实现 只是简单地比较对象的内存地址。您可以使用 覆盖 java.lang.Object中定义的equals()方法的默认实现。如果你重写equals(),你必须重写 hashCode()。否则,违反总体合同 Object.hashCode将发生,当您的类与所有基于散列的集合结合使用时,可能会产生意想不到的影响 。

来源:http://www.xyzws.com/javafaq/why-always-override-hashcode-if-overriding-equals/20(看看它,它有很好的例子)。

结论:您只需要覆盖equals进行简单比较。但是,对于其他方面,例如基于哈希的集合,您应该也覆盖hashCode