复习equals、hashCode的知识点

Object 内部equals实现

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

上述的代码表明,如果是调用Object的equals,实际上是比较两个对象的内存地址是否一致。

equals和==区别

这个问题在面试中是经常被问,我们都知道equals是比较两个对象的值,而==是比较的两个对象的内存地址。但是从严格意义上说是有问题的。

            Car c= new Car(12);
            Car c1 =new Car(23);
            System.out.println(c.equals(c1));//false
            System.out.println(c==c1);//false

这里你在调用equals实际上是调用的是Object的equals(还是比较的是内存地址)。你可以通过重写equals方法。

重写equals的规则

  • 自反性。对于任何非null的引用值x,x.equals(x)应返回true。
  • 对称性。对于任何非null的引用值x与y,当且仅当:y.equals(x)返回true时,x.equals(y)才返回true。
  • 传递性。对于任何非null的引用值x、y与z,如果y.equals(x)返回true,y.equals(z)返回true,那么x.equals(z)也应返回true。
  • 一致性。对于任何非null的引用值x与y,假设对象上equals比较中的信息没有被修改,则多次调用x.equals(y)始终返回true或者始终返回false。
  • 对于任何非空引用值x,x.equals(null)应返回false。(不要使用null.equals(x) 会出现空指针异常)

equals混合了继承

public class Car {
    private int size;
    public Car(int size) {
        super();
        this.size = size;
    }
    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        if(obj instanceof Car) {
            Car c = (Car)obj;
            return c.size==size; /这里比较的依据是看size
        }
        return super.equals(obj);
    }
}
public class AppleCar extends Car {
    private int count;
    public AppleCar(int size, int count) {
        super(size);
        this.count = count;
    }
    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        if(obj instanceof AppleCar) {
            AppleCar ac = (AppleCar)obj;
            return ac.count==count;
        }
        return super.equals(obj);//这里会调用父类的Car的equal比较规则,
        //虽然车的类型不同,但是车的size是否一致,作为最终判断依据
        //return false;则这里就表示不是同一种类型的就是不相等
    }
}
            Car c= new Car(23);
            Car c1 =new AppleCar(23,15);
            System.out.println(c.equals(c1));//true
            System.out.println(c1.equals(c));//ture

出现这样的问题就是在于instanceof 违法了对称性,你只能顺着实例对象的方向比较。从而我们在不是实例对象的时候,调用父类的equals来比较。

扫描二维码关注公众号,回复: 2996998 查看本文章

为啥重写equals要重写hashcode

hashCode的意思就是散列码,也就是哈希码。在java中,我们可以使用hashCode()来获取对象的哈希码,其值就是对象的存储地址,hashCode()方法出自Object。

           String s = "ok";
           String t = new String("ok");
           System.out.println(s.hashCode()+" "+t.hashCode());//hashcode的值一样。

String 方法的Hashcode方法

   public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

我们可以看出,字符串s与t拥有相同的散列码,这是因为字符串的散列码是由内容导出的,它重写了Object的Hashcode方法。Object类默认的hashCode方法计算出来的对象存储地址,所以不同的对象,它的地址肯定不一样。

equals和Hashcode

和hashcode重写的equals方法应该是比较两个对象的值是否相等。

    String a = new String("a");
            String b = new String("a");
            System.out.println(a.equals(b));//true
            System.out.println(a==b);//false
            System.out.println(a.hashCode());//97
            System.out.println(b.hashCode());//97

由这个例子可以看出两个对象的equals(比较的是内容)相等,这两个对象的hashcode,必然相等。如果是同一个对象,那肯定内容相等,所以说必须要覆盖equals,比较内容。

  • 如果两个对象通过调用equals方法是相等的,那么这两个对象调用hashCode方法必须返回相同的整数。
  • 两个对象的hashcode相等。并不代表这两个对象equals相等,通过哈希函数产生的hashcode会1产生一个等价类,在这个等价类中的hashcode值都相等。
  • 如果两个对象通过调用equals方法是不相等的,不要求这两个对象调用hashCode方法必须返回不同的整数。但是程序员应该意识到对不同的对象产生不同的hash值可以提供哈希表的性能。
         Map map = new HashMap<>();
         String s="ok";
         String s1 = "ok";
         map.put(s, "one");
         System.out.println(map.get(s1));//one
         System.out.println(map.get(s));//one
         Car c = new Car();
         Car c1 = new Car();
         map.put(c,"kkk");
         System.out.println(map.get(c));//kkk
         System.out.println(map.get(c1));//null

这里在最后map取值,是根据key的hashcode,来取值,String因为重写了hashcode方法,是根据内容去计算的,所以内容相等,即hashcode相等;而Car的hashcode默认是object,即就是根据对象地址,两个不同的对象,hashcode肯定不一样,所以无法获取值。

上面的方法我们可以通过重写hashcode。我们在重写equals的时候,一定要重写hashcode方法。

重写equals()中getClass与instanceof的区别

一般都是推荐使用 getClass 来进行类型判断,保证是同一个类的对象。但是有些时候还是会用到instanceof,这个主要看需求。

参考引用:Java核心技术基础知识

猜你喜欢

转载自blog.csdn.net/qq_33188563/article/details/81876967