• object的hashCode与equals


    JAVA代码:
        public static void main(String[] args)
        {
            Object obj1 = new Object();
            Object obj2= new Object();
            Object obj3 = obj2;
            System.out.println("obj1==obj2 ?"+obj1.equals(obj2));
            System.out.println("obj2==obj3 ?"+obj2.equals(obj3));
            
            System.out.println("obj1's hashcode: "+obj1.hashCode());
            System.out.println("obj1's hashcode: "+obj2.hashCode());         System.out.println("obj1's hashcode: "+obj3.hashCode()); 
        }
    }

    输出结果:
    obj1==obj2 ?false
    obj2==obj3 ?true
    obj1's hashcode: 12677476
    obj1's hashcode: 33263331
    obj1's hashcode: 33263331

                                             总结
    API Object类中源代码:
     public boolean equals(Object obj) {
        return (this == obj);
        }
         也就是当我们写了一个自己的class,然后用class new了两个对象,如果在这两个对象上用equals时,此时比较的两个引用是不是一样,也就是他们的物理地址是不是一样,如果不一样的话,就会返回false.
        我们实际用的时候,往往不是希望比较两个对象的物理地址是不是一样,而比较两个对象的属性等东西是不是一样,所以Object提供的方法往往不能满足我们要求。
        这就需要我们覆盖Object的equals方法。

        如果要覆盖Object的equals的方法,一定要满足以下几个等价关系:
    1. 自反性,对于任何非null的引用值x,x.equals(x)必须反回true
    2. 对称性,对于任何非null的引用值x,y,当且仅当y.equals(x)返回true时,x.equals(y),才返回true.
    3. 传递性,对于任何非null的引用值x,y,z,如果x.equals(y)返回true,并且y.equals(z)返回ture,那
        么x.equals(z)也必须返回true.
    4. 一致性,对于任何非null的引用值x,y,只要equals比较操作的两个对象中所用的信息没有被修改,多次
        调用x.equals(y)就会一致的返回true,或者一致的返回false.
    5.对于任何的非null的值x,x.equals(null),必须返回false .

    如果我们的程序中没有完全遵守这些约定,那么你的程式就有可能发生问题。

    没有出问题的原因是,因为你的程序没有地方 直接调用 或者 间接调用 equals方法。
    什么是直接调用equals ,什么是间接调用equals呢?
    直接调用equals方法就是说,你显式的在你的程序中对你自己的写的对象上面调用equals方法,
    间接调用呢,用一简单的例子来说,当我们平常会把一个些对象放到collection,为了不重复,我们有调用collection的contains方法,此时就间接调用了collection中对象的equals方法。

    覆盖了equals的类中,也必须覆盖hashCode方法

    简单的结论:当对象类没有不符合规范的override equals()和hashcode()方法的时候,两个对象做比较

    1. 如果equals()比较相同,那么hashcode()肯定相同。
    2. 如果hashcode()比较相同,那么equals()不一定相同。

    众所周之,String 、Math、还有Integer、Double。。。。等这些封装类重写了Object中的equals()方法,让它不再比较句柄(引用),而是比较对象中实际包含的整数的值,即比较的是内容。

    而Object的equals()方法比较的是地址值。
    一般来说,如果你要把一个类的对象放入容器中,那么通常要为其重写equals()方法,让他们比较地址值而不是内容值。特别地,如果要把你的类的对象放入散列中,那么还要重写hashCode()方法;要放到有序容器中,还要重写compareTo()方法。

    为什么要重写hashCode方法? 
    我们应该先了解java判断两个对象是否相等的规则。 在java的集合中,判断两个对象是否相等的规则是:

    首先,判断两个对象的hashCode是否相等 
    如果不相等,认为两个对象也不相等 
    如果相等,则判断两个对象用equals运算是否相等 
    如果不相等,认为两个对象也不相等 
    如果相等,认为两个对象相等 

    关于Object类的hashCode()方法的特点:
    a) 在Java应用的一次执行过程当中,对于同一个对象的hashCode方法的多次调用,他们应该返回同样的值(前提是该对象的信息没有发生变化)。
    b) 对于两个对象来说,如果使用equals方法比较返回true,那么这两个对象的hashCode值一定是相同的。
    c) 对于两个对象来说,如果使用equals方法比较返回false,那么这两个对象的hashCode值不要求一定不同(可以相同,可以不同),但是如果不同则可以提高应用的性能。
    d) 对于Object类来说,不同的Object对象的hashCode值是不同的(Object类的hashCode值表示的是对象的地址)。

    当使用HashSet时,hashCode()方法就会得到调用,判断已经存储在集合中的对象的hash code值是否与增加的对象的hash code值一致;如果不一致,直接加进去;如果一致,再进行equals方法的比较,equals方法如果返回true,表示对象已经加进去了,就不会再增加新的对象,否则加进去。

    我们在equals方法中需要向下转型,效率很低,所以先判断hashCode方法可以提高效率。

    equals()相等的两个对象,hashcode()一定相等; 
    equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。 
    反 过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。

  • 相关阅读:
    静态字段==全局变量
    异常处理原则
    结合冒泡排序学习委托和事件系列一
    Linq详解
    linq的延迟执行和立即执行
    统计一个目录下所有.cs文件的行数
    Multicast委托和Observer模式——委托系列二
    usb设备插入电脑,电脑显示MTP带有黄色感叹号,(Windows已找到设备的去驱动程序,但在尝试安装他们时遇到错误),解决办法
    博客地址变更
    Flex在线阅读 FlexBook FlexPaper
  • 原文地址:https://www.cnblogs.com/lulu638/p/4096234.html
Copyright © 2020-2023  润新知