==与equals与hashCode

==与equals

== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。
equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:
情况 1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
情况 2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。

==

其实对于==,不必去区分是基本数据类型,还是对象的引用类型,比较的都是存的值而已,只不过需要注意的是:java中,基本数据类型存的就是实际的值,比如整型的具体值;而引用对象的变量,存的是堆空间的地址。
这里尤其要注意字符串类型,因为java对字符串的特殊处理,用双引号包含的字符串是保存在字符串常量池的,当多个字符串引用变量指向这个字符串时,实际上指向的是同一个内存区域,==必然返回true;
但是,如果是new出来的字符串对象,此时引用变量再指向的是这个对象在堆空间的具体地址,如果另外一个引用变量指向其他空间地址(比如字符串场景池中的地址),==返回的必然是false。

对于字符串,还需要注意运算符号“+”的处理,两个字符串对象+运算,首先会将两个字符串值进行相加,然后查找字符串常量池,如果已经存在,则直接将字符串常理池的对象作为返回结果;如果字符串常理池中没有,则会在字符串常量池中新建一个字符串对象,并返回。这样在进行==运算时,需要将各个对象搞清楚,否则可能导致判断错误。

另外,其实相应的注意事项应该在 != 时,也要重视。

equals

需要分两种情况:
如果对象没有实现equals方法,则采用==进行判断;
如果对象又实现equals方法,则根据该方法得到具体的返回值。
注意,这里的返回值完全是由equals方法决定,并不与两个对象的地址、内容等完全相关,比如,如果equals方法直接返回true或false,那么两个对象不论是否是同一个对象,或内容是否相等,都不会对equals的结果带来不同。当然,一般情况下,java封装的对象中实现的equals方法,都是比较地址或内容。比如,字符串对象的equals方法:

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        } else {
            if (anObject instanceof String) {
                String aString = (String)anObject;
                if (this.coder() == aString.coder()) {
                    return this.isLatin1() ? StringLatin1.equals(this.value, aString.value) : StringUTF16.equals(this.value, aString.value);
                }
            }

            return false;
        }
    }

==与equals

二者其实并没有原始的关联,仅仅只是equals在实现时,可能会用到==,但由于我们的使用习惯,往往判断两个东西是否相等时,直接就会使用==,当是两个对象时,计算结果就与我们预期可能会不一致。而且这种错误还比较容易发生,且没有辅助工具来提示我们。
所以,可能一种比较好的办法是:
1.全部用equals来判定两个事物是否相等(判断对象为空时可以使用==)
2.代码中不能出现0、1或字符等硬编码
3.不直接使用基本数据类型,而使用封装类型

hashCode

hashCode()介绍
hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个 int 整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在 JDK 的 Object.java 中,这就意味着 Java 中的任何类都包含有 hashCode() 函数。
散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)

hashCode与equals

hashCode()与 equals()的相关规定

  • 如果两个对象相等,则 hashcode 一定也是相同的
  • 两个对象相等,对两个对象分别调用 equals 方法都返回 true
  • 两个对象有相同的 hashcode 值,它们也不一定是相等的
  • 因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
  • hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

第一条,两个对象相等,hashCode也不一定相同,比如equals重写了;
第二条,废话,没有任何意义;
第三条,其实也是废话,因为这根本与我们要讨论的二者关系没有半毛钱的关联,本文中可以完全不关心(当然,实际散列表在应用的时候就是应用的这一条);

注意!散列表有个特性,就是一个散列表中不能存在相等的多个对象,即调用对象的equals不能相等 。
散列表有个特性,就是一个散列表中不能存在相等的多个对象,即调用对象的equals不能相等 。(这个才是核心!)

但是,为了效率,才引出一个hashCode的概念。
插入散列表的时候,首先会调用对象的hashCode计算哈希值,
1.如果值不重复,则直接插入散列表;
2.如果值重复,再调用对象的equals判定是否对象相等,相等时就不再插入散列表,否则仍然会插入散列表

如果重写了类的equals方法,那么可能会导致,原生hashCode算法结果不同的两个对象写入了散列表,而此时,这两个对象又有可能Equals,导致了矛盾:
所以,在涉及到散列表时,如果重写了类的Equals,必须重写类的hashCode,以避免,两个对象Equals的时候,hashCode却不同,即能保证,两个对象相等(Equals)的时候,不会被重复插入散列表(具体怎么重写,待后续学习)。

另外一方面,如果不涉及到类对应的散列表时,跟Equals跟hashCode没有半毛钱关系,二者重写与否可以完全不用关心

发布了1 篇原创文章 · 获赞 0 · 访问量 31

猜你喜欢

转载自blog.csdn.net/weixin_44521516/article/details/104628469