zoukankan      html  css  js  c++  java
  • 为什么重写equals一定要重写hashCode?

    大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白,以下是我的一些个人理解。

    这是Object类关于这两个方法的源码,可以看出,Object类默认的equals比较规则就是比较两个对象的内存地址。而hashcode是本地方法,java的内存是安全的,因此无法根据散列码得到对象的内存地址,但实际上,hashcode是根据对象的内存地址经哈希算法得来的。

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

    上图展示了Student类的重写后的equals方法和hashcode方法,建议大家用eclipse自动生成,尽量不要自己敲因为很有可能会出错。

    现在有两个Student对象:

    Student s1=new Student("小明",18);

    Student s2=new Student("小明",18);

    此时s1.equals(s2)一定返回true

    /*
     * 
     * 
     * equals的使用
     * 
     * */
    package com.tinaluo.java;
    
    import java.awt.Color;
    
    class Cat {
        private String name;
        private int age;
        private double weight;
        private Color color;
    
        public Cat(String name, int age, double weight, Color color) {
            this.name = name;
            this.age = age;
            this.weight = weight;
            this.color = color;
        }
    
        /*
         * equals改写后必须重写hashCode()方法,对象相同则hashCode必须相同!
         * 1、equals()相同,则hashCode必须相等
         * 2、hashCode不相同等,则equals()必不相等
         * 
         * @see java.lang.Object#hashCode()
         */
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + age;
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            return result;
        }
        @Override
        public boolean equals(Object obj) {
            if(this==obj){
                return true;
            }
            if(obj==null){
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            Cat cat = (Cat) obj;
            return name.equals(cat.name) && (age == cat.age)
                    && (weight == cat.weight) && (color.equals(cat.color));
        }
    }
    
    public class InternalLoad {
        public static void main(String[] args) {
            Cat a = new Cat("java", 12, 21, Color.BLACK);
            Cat b = new Cat("C++", 12, 21, Color.WHITE);
            Cat c = new Cat("java", 12, 21, Color.BLACK);
            System.out.println(a.equals(b));
            System.out.println(a.equals(c));
            System.out.println(a.hashCode() == c.hashCode());
        }
    }

    假如只重写equals而不重写hashcode,那么Student类的hashcode方法就是Object默认的hashcode方法,由于默认的hashcode方法是根据对象的内存地址经哈希算法得来的,显然此时s1!=s2,故两者的hashcode不一定相等。

    然而重写了equals,且s1.equals(s2)返回true,根据hashcode的规则,两个对象相等其哈希值一定相等,所以矛盾就产生了,因此重写equals一定要重写hashcode,而且从Student类重写后的hashcode方法中可以看出,重写后返回的新的哈希值与Student的两个属性有关。

    以下是关于hashcode的一些规定:

    关键结论:

    两个对象相等,hashcode一定相等
    两个对象不等,hashcode不一定不等
    hashcode相等,两个对象不一定相等
    hashcode不等,两个对象一定不等

  • 相关阅读:
    vue自定义指令
    ZOJ Problem Set–2104 Let the Balloon Rise
    ZOJ Problem Set 3202 Secondprice Auction
    ZOJ Problem Set–1879 Jolly Jumpers
    ZOJ Problem Set–2405 Specialized FourDigit Numbers
    ZOJ Problem Set–1874 Primary Arithmetic
    ZOJ Problem Set–1970 All in All
    ZOJ Problem Set–1828 Fibonacci Numbers
    要怎么样调整状态呢
    ZOJ Problem Set–1951 Goldbach's Conjecture
  • 原文地址:https://www.cnblogs.com/tinaluo/p/10207584.html
Copyright © 2011-2022 走看看