zoukankan      html  css  js  c++  java
  • 为什么要重写equals()方法与hashCode()方法

    在java中,所有的对象都是继承于Object类。Ojbect类中有两个方法equals、hashCode,这两个方法都是用来比较两个对象是否相等的。

    在未重写equals方法我们是继承了object的equals方法,那里的 equals是比较两个对象的内存地址,显然我们new了2个对象内存地址肯定不一样

    • 对于值对象,==比较的是两个对象的值
    • 对于引用对象,比较的是两个对象的地址

    Object 默认的equals方法同==,一般来说我们的对象都是引用对象,要重写equals方法。

    1     public boolean equals(Object obj) {
    2         return (this == obj);
    3     }
    1     public static void main(String[] args) {
    2         Object c=new Object();
    3         Object d=new Object();
    4         System.out.println(c.equals(d));//false
    5 
    6     }

    这个比较下,结果是false,也就是这两个对象不一样,但是有些业务,我们需要证明一个类的下面的实例对象时相等的,这时候我们就必须重写equlas方法了。

    如下代码,我们新建一个对象Student,并重写equals与hashCode方法

     1 public class Student {
     2 
     3     private int no;
     4 
     5     private String name;
     6 
     7 
     8     @Override
     9     public boolean equals(Object o) {
    10         if (this == o) return true;
    11         if (o == null || getClass() != o.getClass()) return false;
    12 
    13         Student student = (Student) o;
    14 
    15         if (no != student.no) return false;
    16         return !(name != null ? !name.equals(student.name) : student.name != null);
    17 
    18     }
    19 
    20     @Override
    21     public int hashCode() {
    22         int result = no;
    23         result = 31 * result + (name != null ? name.hashCode() : 0);
    24         return result;
    25     }
    26 
    27     public int getNo() {
    28         return no;
    29     }
    30 
    31     public void setNo(int no) {
    32         this.no = no;
    33     }
    34 
    35     public String getName() {
    36         return name;
    37     }
    38 
    39     public void setName(String name) {
    40         this.name = name;
    41     }
    42 }
    1         Student a=new Student();
    2         Student b=new Student();
    3         System.out.println(a.equals(b));//ture    

    此时可以看出a、b对象相等.

    hashCode方法也是可以用来比较两个对象是否相等的。但是我们很少使用,应该说是很少直接使用。hashCode方法返回的是一个int值,可以看做是一个对象的唯一编码,如果两个对象的hashCode值相同,我们应该认为这两个对象是同一个对象。

    一般如果使用java中的Map对象进行存储时,他会自动调用hashCode方法来比较两个对象是否相等。

    所以如果我们对equals方法进行了重写,建议一定要对hashCode方法重写,以保证相同的对象返回相同的hash值,不同的对象返回不同的hash值。

    1、重写equals方法时需要重写hashCode方法,主要是针对Map、Set等集合类型的使用;

    a: Map、Set等集合类型存放的对象必须是唯一的;

    b: 集合类判断两个对象是否相等,是先判断equals是否相等,如果equals返回TRUE,还要再判断HashCode返回值是否ture,只有两者都返回ture,才认为该两个对象是相等的。

    2、由于Object的hashCode返回的是对象的hash值,所以即使equals返回TRUE,集合也可能判定两个对象不等,所以必须重写hashCode方法,以保证当equals返回TRUE时,hashCode也返回Ture,这样才能使得集合中存放的对象唯一。

    个人感觉equals重写,是站在使用的角度上考虑的:类设计者不希望通过内存地址来比较两个对象是否相等,重写这个equals方法,能够方便的使用Collection<E>操作自定义对象E(Collection中很多方法涉及E.equals()的);而hashCode的重新,是方便Map<K,V>的使用,良好的自定义hashCode,会极大的提高Map的使用效率。
    
    为啥说equals重新时,一定要重写hashCode?感觉这么理解不知行不行:既然自定义类重写了equals方法,说明类设计者不希望通过内存地址来比较两个对象是否相等了。而Object的hashCode也是对象的内存地址,既然不希望通过地址比较对象,那么以内存地址作为hashCode也就没有实际使用意义了,索性将自定义对象的hashCode方法也重写了吧!

    参考: hashCode的作用   重写equals方法为什么要重写hashCode方法

  • 相关阅读:
    模板方法模式
    备忘录模式
    观察者模式
    中介者模式
    迭代器模式
    Char型和string型字符串比较整理
    命令模式
    责任链模式
    代理模式
    dokcer 杂谈
  • 原文地址:https://www.cnblogs.com/huzi007/p/5383161.html
Copyright © 2011-2022 走看看