我们知道java中所有的类都有equals方法,因为Object类拥有equals方法

 



object对象中的 public boolean equals(Object obj),指示其他某个对象是否与此对象“相等”。这里的相等指的是比较的两方指向同一个对象



对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象(就是同一块内存地址),此方法才返回 true;



但是这一性质并不符合我们生活所需,比如一个不允许有重复值的对象数组,我们的规定,保存的数据相同的对象就属于重复对象,当我们往数组内插入对象时,数组必然要先判断插入的对象是否存在,如果存在就替换,不存在就插入,但是用equals方法显然判断不出,因为new出来的对象的内存地址永远不同,所以数组中就会出现重复值。这时候显然就要重写数组类的equals方法了,在其中加入我们自己的逻辑。




Jdk的api建议:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode



hashCode



(1)当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true 
(2)当obj1.hashCode() == obj2.hashCode()为false时,obj1.equals(obj2)必须为false




所以当我们重写了equals方法之后,我们的加入了自己的逻辑。还是上面那个数组的例子,我们重写了equals方法,并规定只要对象的所有属性值相同,两个对象就相等,很显然我们的目的可以轻松达到。但是我们的没有重写hashCode方法。hashCode方法仍然返回的对象的内存地址,所以两个对象的hashCode值还是不相等,这就违反了hashCode



违反这个协定有什么后果呢,在某些利用对象hashCode值做索引的情况下,这样会造成混乱。相当于你没重写equals方法。




例子:




[java]  view plain  copy

 

1. class Person{  
2. public String name;  
3. private int age;  
4. public Person(String name,int age) {  
5. this.name = name;  
6. this.age = age;  
7.     }  
8.       
9. //这里我重写equals方法,规定只要Person的所有属性值相等。两个对象就相等  
10. @Override  
11. public boolean equals(Object obj) {  
12. if(obj == this) return true;  
13. if(obj instanceof Person){  
14. try {  
15. true;  
16.                 Field[] objectFields = obj.getClass().getDeclaredFields();  
17.                 Field[] PersonFields = obj.getClass().getDeclaredFields();  
18. for(int i = 0;i< objectFields.length;i++){  
19. if(!objectFields[i].get(obj).equals(PersonFields[i].get(this))){  
20. false;  
21. break;  
22.                     }  
23.                 }  
24. return check;  
25.                   
26. catch (Exception e) {  
27. // TODO Auto-generated catch block  
28.                 e.printStackTrace();  
29.             }  
30. return true;  
31.         }  
32. return false;  
33.     }  
34.   
35. //重写hashCode方法,把对象的name和age属性转为一个字符串,返回次字符串的hashCode值  
36. @Override  
37. public int hashCode() {  
38. this.name + this.age + "";  
39. return id.hashCode();  
40.     }  
41.       
42. }  
43.   
44. public class ObjectDemo {  
45. public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {  
46. new Person("fanjie",23);  
47. new Person("fanjie",23);  
48.   
49.         System.out.println(p.equals(p2));  
50.         System.out.println(p.hashCode() == p2.hashCode());  
51.           
52.     }  
53.       
54.       
55. }




需要说明的是equals方法的重写还有很多规定:




  • 自反性:对于任何非空引用值 xx.equals(x) 都应返回 true
  • 对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true
  • 传递性:对于任何非空引用值 xy 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true
  • 一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
  • 对于任何非空引用值 xx.equals(null) 都应返回 false。