我们常常听说重写.equals() ,hashCode()其中一个方法,则必须重写另外一个方法
今天我们来看看为什么要这么做呢?
作用:
== 比较两个对象地址是否相同
.equals()比较两个对象是否相同
hashCode()计算对象的hash值
java中每个类都继承与object类,Object类中就有equals方法。
如果不复写equals()方法的话,这默认Object类中的equals方法。
Objecte quals方法
1 public boolean equals(Object obj) { 2 return (this == obj); 3 }
可以看到默认情况下比较两个对象是否相同其实就是比较对象地址是否相同。
当然也会在特定的业务场景的场景下,存在复写equals方法的情况。比如String的equals()的方法就是重写了的
String equals方法
1 public boolean equals(Object anObject) { 2 if (this == anObject) {//1 3 return true; 4 } 5 if (anObject instanceof String) { 6 String anotherString = (String)anObject; 7 int n = value.length; 8 if (n == anotherString.value.length) {//2 9 char v1[] = value; 10 char v2[] = anotherString.value; 11 int i = 0; 12 while (n-- != 0) {//3 13 if (v1[i] != v2[i]) 14 return false; 15 i++; 16 } 17 return true; 18 } 19 } 20 return false; 21 }
1.如果比较的对象和当前对象是同一个对象,返回true
2.比较的String长度,如果与当前长度不相同则不同
3.因为String的数据结构使用的是char的数组。循环遍历char数组,当遇到相同位置char不同就返回false,全部相同则返回true。
String的equals()比较的是两个String的字面量是否相同。
我们都知道比较两个对象的地址对系统消耗太大,所以我们不希望每次比较对象是否相同都比较地址。
这时候就会用到对象的的hash(散列)值,每当jvm创建一个对象都会为他创建一个独一无二的hash值。
如果两个对象的hash值不同代表他们肯定不是同一个对象
如果两个对象的hash值相同,他们仍然可能不是同一个对象(概率很低),这个时候在进行地址比较判断是否是相同对象。
Object hashCode方法
1 public native int hashCode();
好的基本的知识点都说完了,我们来看看为什么常常听说重写.equals() ,hashCode()其中一个方法,则必须重写另外一个方法。
现在我们新建一个HashSet<String>
Set的数据类型保证数据是无序和唯一的。
也就是说保证字面量相同的的String有且出现一次。
现在我们不重写hashCode的方法会发生什么?
1 String A=new ("String"); 2 String B=new ("String");
其实这个Set中只需要存在一个“String”的字面量。
但是但我们比较这两个对象hash值的时候发现他们两个hash值不同,程序会判定他们是两个不同的对象,所以把这两个对象都添加进了Set中,这根本不是我们想要的目的,我们还希望比较String的字面量。
String hashCode方法
1 public int hashCode() { 2 int h = hash; 3 if (h == 0 && value.length > 0) { 4 char val[] = value; 5 6 for (int i = 0; i < value.length; i++) { 7 h = 31 * h + val[i]; 8 } 9 hash = h; 10 } 11 return h; 12 }
总结:
== 比较两个对象的地址,不可重写
.equals() 默认比较地址,程序员可重写方法自定义比较
hashCode() 生成对象hash值,一般在.equals()前执行,为了节约比较地址带来的系统开销。
当然重写其中一个方法.equals(),hashCode() 都需要重写另一个方法
他们是搭档起来就是判断对象是否相同(hashCode()在前,.equals()在后)