Object类中equals和==是一个意思:比较2个对象的内存地址是否相同。
下面来看String这个封装类:覆写了equals方法和hashcode方法,
equals方法:
1.首先比较2个对象的地址是否相同,如果相同当然是一个对象
2.比较字符串每一个字符是否相等。
hashcode方法:相同字符串(无论是基础类型还是封装类型),计算出的hashcode都是一样的。
做一个例子:
下面来看下自义定的类:
只覆写此类中的equals方法:
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Person)){
//不是同类对象
return false;
}
Person obj_person=(Person)obj;
if(this.name.equals(obj_person.name)){
return true;
}else{
return false;
}
}
//只覆写了equals方法
Person personA=new Person("hx",12);
Person personB=new Person("hx",19);
System.out.println("personA和personB两个是同一个对象吗 (==)?"+(personA==personB));//false
System.out.println("personA和personB equals吗 (equals)?"+(personA.equals(personB)));//true
System.out.println("personA的hashcode:"+personA.hashCode());//809191624
System.out.println("personB的hashcode:"+personB.hashCode());//69688117
覆写了equals+hashcode方法:
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Person)){
//不是同类对象
return false;
}
Person obj_person=(Person)obj;
if(this.name.equals(obj_person.name)){
return true;
}else{
return false;
}
}
@Override
public int hashCode() {
//用String类型的name的hashcode 相同的字符串hashcode是相同的,因为在String中覆写了hashcode
return this.name.hashCode()*16;
}
//覆写equals+hashcode方法
Person personA=new Person("hx",12);
Person personB=new Person("hx",19);
Person personC=personA;
Person personD=new Person("hx",12);
System.out.println("personA和personB两个是同一个对象吗 (==)?"+(personA==personB));//false
System.out.println("personA和personB equals吗 (equals)?"+(personA.equals(personB)));//true
System.out.println("personA的hashcode:"+personA.hashCode());//53504
System.out.println("personB的hashcode:"+personB.hashCode());//53504
System.out.println("personD的hashcode:"+personD.hashCode());//53504
System.out.println("personC与personA是是同一个对象吗(==)?"+(personA==personC));//true
System.out.println("personA和personD两个是同一个对象吗 (==)?"+(personA==personD));//false
System.out.println("personA和personD两个是同一个对象吗 (equals)?"+(personA.equals(personD)));//true
结论:
未覆写equals情况下,A.equals(B) 或 A == B ,hashcode肯定相同(废话,未覆写的时候equals也是==)
覆写equals 情况下, A==B hashcode相同, A.equals(B) hashcode不一定相同(equals通过某一个属性来判断,比如name)
hashcode相同,并不一定相等(equals或==)。
1.非基本数据类型说相等要分清(==还是equals)
2.在不覆写的情况下,对象的equals也是调用== ,使用的是Object的方法,比较的还是内存地址值。
3.无论是覆写了equals 或 hashcode 还是 equals+hashcode,==只与内存地址有关,与equals还有hashcode是否覆写完全无关。
equals覆写后,A.equals(B)与hashcode是否覆写无关,只与你的覆写equals方法内的逻辑有关。
hashcode覆写,与hashset、hashmap等这种散列集合有关。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
☆重点:hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable。
当集合HashMap要添加新的对象时,先调用这个对象的hashCode方法,得到对应的hashcode值,实际上在HashMap的具体实现中会用一个table保存已经存进去的对象的hashcode值,如果table中没有该hashcode值,它就可以直接存进去,不用再进行任何比较了;如果存在该hashcode值, 就再调用它的equals方法与新元素进行比较,相同的话就覆盖,不相同就散列其它的地址 ,说通俗一点:Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。
如果不覆写hashcode方法,
Person p1 = new Person("Jack", 12);//p1
System.out.println(p1.hashCode());
HashMap<Person , Integer> hashMap = new HashMap<Person , Integer>();
hashMap.put(p1, 1);
System.out.println(hashMap.get(new Person ("Jack", 12)));//p2
get返回的是null
只覆写的equals的情况下(不产生hash冲突的前提下),person1存入了hashmap,而person1.equals(person2) ----true 业务上可以理解为2个对象是相同的,但是用person2去hashmap中get的时候,由于hashcode没有覆写,导致person1和person2的hashcode不相等,所以hashmap取不到返回null.