美文网首页
当被问到为什么要重写equals和hashcode方法

当被问到为什么要重写equals和hashcode方法

作者: 互联网修真院 | 来源:发表于2019-10-25 21:34 被阅读0次

    面试的时候老是会问到为什么要重写equals和hashcode方法。其实这个问题里面包含好几个问题,我们通过源码一一拆解就知道了!

    1. equals() 比较的是什么?

    2. hashcode() 方法是什么?

    3. 为什么要重写equals()?

    4. 为什么要重写hashcode() 方法,不重写可以?

    首先我们要知道equals() 和hashcode() 是基类 java.lang.Object自带的方法。

    public native int hashCode();
    
    public boolean equals(Object obj) {
    
    return (this == obj);
    
    }
    

    hashcode() 是一个本地方法,返回的是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值(解释来自于百度百科)。equals()方法默认比较的就是对象本身,其实就是内存地址

    那么有一个问题,如果new了两个属性值一样的对象,它们对于java来说是不equal的,因为对于java来说两个对象指向的是两个不同的内存地址。但是一般我们希望如果对象的属性值一样,那么我们就判断这两个对象相等。 那么就需要重写equals()。

    下面我设计一个User类,包含id和realName属性。我认为只要id和name相同,那么就认为两个对象 相等。
    ps :重写 toString() 和equals() ,建议用IDE自带的工具来生成。

      public class User {
        private String id;
        private String realName;
    
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public String getRealName() {
            return realName;
        }
        public void setRealName(String realName) {
            this.realName = realName;
        }
        public User(String id, String realName) {
            this.id = id;
            this.realName = realName;
        }
        @Override
        public String toString() {
            return "User{" +
                    "id='" + id + '\'' +
                    ", realName='" + realName + '\'' +
                    '}';
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            User user = (User) o;
            return Objects.equals(id, user.id) &&
                    Objects.equals(realName, user.realName);
        }
    }
    
    public class OverrideHashcode {
        public static void main(String[] args) {
           Set<User> data = new HashSet<>();
            User a = new User("1001","小叶檀");
            User b = new User("1001","小叶檀");
            data.add(a);
            data.add(b);
            System.out.println("没有重写hashcode前:"+data.toString());
            System.out.println("两个对象是否相等:"+(a.equals(b)));
        }
    }
    

    运行后打印结果:
    没有重写hashcode前:[User{id='1001', realName='小叶檀'}, User{id='1001', realName='小叶檀'}]
    两个对象是否相等:true

    在没重写hashcode()时,默认是以对象的内存地址来参与计算hash码的。
    因为内存地址不同,那么得到的hash码也不一样,那么对于hashset来说就被认为是两个不同的对象。

    两个相同的实例却有不同的hashcode, 这样就有点违背hashset的原则了。
    所以需要重写hashcode()。

    @Override
        public int hashCode() {
            return Objects.hash(id, realName);
        }
    

    重写完后再执行main方法,发现set里面只有一个对象了。 大功告成!

    总结

    equals()默认比较内存地址,与业务而言意义不大,重写equals()为了结合业务体现对象的真实性。

    hashcode()默认是取的对象的内存地址去计算散列码,业务上认为相同的实例所得到的hashcode却不同。 重写hashcode()就是为了能运用那些基于hash标识对象唯一性的集合类。

    在这里估计就会有人问到String的equals()默认比较的就是里面的内容,不是内存地址。下一篇文章就整理跟String相关的面试题。

    相关文章

      网友评论

          本文标题:当被问到为什么要重写equals和hashcode方法

          本文链接:https://www.haomeiwen.com/subject/azkevctx.html