该帖已经被评为新手帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-05-31
最后修改:2010-06-01
对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals方法了。 2. Object类中的equals方法就是用'=='来比较的,所以如果没有重写equals方法,equals和==是等价的。 通常我们会重写equals方法,让equals比较两个对象的内容,而不是比较对象的引用(地址)因为往往我们觉得比较对象的内容是否相同比比较对象的引用(地址)更有意义。 3. Object类中的hashCode是返回对象在内存中地址转换成的一个int值(可以就当做地址看)。所以如果没有重写hashCode方法,任何对象的hashCode都是不相等的。通常在集合类的时候需要重写hashCode方法和equals方法,因为如果需要给集合类(比如:HashSet)添加对象,那么在添加之前需要查看给集合里是否已经有了该对象,比较好的方式就是用hashCode。 4. 注意的是String、Integer、Boolean、Double等这些类都重写了equals和hashCode方法,这两个方法是根据对象的内容来比较和计算hashCode的。(详细可以查看jdk下的String.java源代码),所以只要对象的基本类型值相同,那么hashcode就一定相同。 5. equals()相等的两个对象,hashcode()一般是相等的,最好在重写equals()方法时,重写hashcode()方法; equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。 反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。在object类中,hashcode()方法是本地方法,返回的是对象的引用(地址值),而object类中的equals()方法比较的也是两个对象的引用(地址值),如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了。 以下是测试代码。 public class Equals_HashCode { public static void main(String[] args) { String a = new String("str"); String b = new String("str"); System.out.println(a==b); System.out.println(a.equals(b)); System.out.println(a.hashCode()); System.out.println(b.hashCode()); // 输出 false true 114225 114225 class A{ String str; int i; public A(String str, int i) { super(); this.str = str; this.i = i; } } A aA = new A("str",1); A bA = new A("str",1); System.out.println(aA==bA); System.out.println(aA.equals(bA)); System.out.println(aA.hashCode()); System.out.println(bA.hashCode()); // 输出 false false 6413875 21174459 class B{ String str; public B(String str){ this.str = str; } } B aB = new B("str"); B bB = new B("str"); System.out.println(aB==bB); System.out.println(aB.equals(bB)); System.out.println(aB.hashCode()); System.out.println(bB.hashCode()); // 输出 false false 827574 17510567 class C{ int i; public C(int i){ this.i = i; } } C aC = new C(1); C bC = new C(1); System.out.println(aC==bC); System.out.println(aC.equals(bC)); System.out.println(aC.hashCode()); System.out.println(bC.hashCode()); //输出 false false 27744459 28737396 } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-06-01
引用 equals()相等的两个对象,hashcode()一定相等; equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。 是这样吗?我做了个测试 class Product { private int id; private String name; public Product(int id, String name) { this.id = id; this.name = name; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (!(obj instanceof Product)) { return false; } Product other = (Product)obj; if (other.id != this.id) { return false; } return true; } } public class EqualsTest { public static void main(String[] args) { Product a = new Product(1, "zcl"); Product b = new Product(1, "chunlei"); System.out.println("equals: " + a.equals(b)); System.out.println("a.hashCode:" + a.hashCode()); System.out.println("b.hashCode:" + b.hashCode()); } } /** (output) D:\My Documents\javacode>javac EqualsTest.java D:\My Documents\javacode>java EqualsTest equals: true a.hashCode:12677476 b.hashCode:33263331 */ 是我理解错了还是楼主讲得有问题? |
|
返回顶楼 | |
发表时间:2010-06-01
五月天 写道 引用 equals()相等的两个对象,hashcode()一定相等; equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。 是这样吗?我做了个测试 class Product { private int id; private String name; public Product(int id, String name) { this.id = id; this.name = name; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (!(obj instanceof Product)) { return false; } Product other = (Product)obj; if (other.id != this.id) { return false; } return true; } } public class EqualsTest { public static void main(String[] args) { Product a = new Product(1, "zcl"); Product b = new Product(1, "chunlei"); System.out.println("equals: " + a.equals(b)); System.out.println("a.hashCode:" + a.hashCode()); System.out.println("b.hashCode:" + b.hashCode()); } } /** (output) D:\My Documents\javacode>javac EqualsTest.java D:\My Documents\javacode>java EqualsTest equals: true a.hashCode:12677476 b.hashCode:33263331 */ 是我理解错了还是楼主讲得有问题? 重写equal方法 一定要重写hashcode方法 |
|
返回顶楼 | |
发表时间:2010-06-01
引用 重写equal方法 一定要重写hashcode方法 也不一定吧?我觉得也只是在处理如HashMap,HashSet等通过哈希储存结构中会使用到hashCode。 当然,在重写equals方法时同时重写hashCode是个好的规范! 我刚才那代码只是想证明:equals方法判断对象相等时,hashCode不一定相等。 |
|
返回顶楼 | |
发表时间:2010-06-01
最后修改:2010-06-01
五月天 写道 引用 重写equal方法 一定要重写hashcode方法 也不一定吧?我觉得也只是在处理如HashMap,HashSet等通过哈希储存结构中会使用到hashCode。 当然,在重写equals方法时同时重写hashCode是个好的规范! 我刚才那代码只是想证明:equals方法判断对象相等时,hashCode不一定相等。 之前没考虑好这个问题,在此表示歉意。《Effective Java》中也提到重写equal方法,规范性地也需要重写hashCode()。 真是知识到用时方狠少呀。 |
|
返回顶楼 | |
发表时间:2010-06-01
tottichen 写道 五月天 写道 引用 重写equal方法 一定要重写hashcode方法 也不一定吧?我觉得也只是在处理如HashMap,HashSet等通过哈希储存结构中会使用到hashCode。 当然,在重写equals方法时同时重写hashCode是个好的规范! 我刚才那代码只是想证明:equals方法判断对象相等时,hashCode不一定相等。 之前没考虑好这个问题,在此表示歉意。《Effective Java》中也提到重写equal方法,规范性地也需要重写hashCode()。 真是知识到用时方狠少呀。 1. 你是不是需要两个object判断相等? 如果如楼上希望的product a product b那样就表示相等的话,在重写一下hashcode就可以了 2. 如果equals认为相等的两个对象,那hashcode一定相等;两个equals认为不相等的对象,hashcode不必需要不等。 3. 为什么equals复写的时候必须复写hashcode 你在使用一些collection framework比如,hashtable的时候,当让希望不equals的对象有不同的hash值。 |
|
返回顶楼 | |
发表时间:2010-06-02
这种浅析很没依据,测试代码也不足以说明观点。
文章苍白无力。 |
|
返回顶楼 | |
发表时间:2010-06-02
2. 如果equals认为相等的两个对象,那hashcode一定相等;两个equals认为不相等的对象,hashcode不必需要不等。
hashCode方法到底返回了什么?如果是对象的引用(地址),那么两个equals不相等时,对象不会有相同的引用吧,引用不同,hashCode必然不等啊?! |
|
返回顶楼 | |
发表时间:2010-06-02
五月天 写道 引用 重写equal方法 一定要重写hashcode方法 也不一定吧?我觉得也只是在处理如HashMap,HashSet等通过哈希储存结构中会使用到hashCode。 当然,在重写equals方法时同时重写hashCode是个好的规范! 我刚才那代码只是想证明:equals方法判断对象相等时,hashCode不一定相等。 对,只是一个规范而已,主要作用是提高对象存在HashMap,HashSet中的查找效率。其它地方用不到 |
|
返回顶楼 | |
发表时间:2010-06-02
banfry 写道 五月天 写道 引用 重写equal方法 一定要重写hashcode方法 也不一定吧?我觉得也只是在处理如HashMap,HashSet等通过哈希储存结构中会使用到hashCode。 当然,在重写equals方法时同时重写hashCode是个好的规范! 我刚才那代码只是想证明:equals方法判断对象相等时,hashCode不一定相等。 对,只是一个规范而已,主要作用是提高对象存在HashMap,HashSet中的查找效率。其它地方用不到 不是查找效率的问题,是如果你equals相等而hashcode不相等时,你在hashMap里会找不到。不是效率问题,是对错问题。 先找hashcode,hashcode不等的,直接认为不等。相等的,再看equals,两者都等,才算等。 |
|
返回顶楼 | |