一号热搜榜,为您提供最新的热搜资讯,热搜榜信息!

面试Java高级职位,却不知道equals源码,我如何用你

百科热搜 作者:蜜蜂攻城狮 热度:758

面试Java高级职位,却不知道equals源码,我如何用你

最近在面试许多工作3-5年应聘者的时候,发现了许多人都没有阅读过String源码,尤其是equals和==的区别的问题以及停留在表层听说层次,没有深入理解。

首先,我们看一下Java的最顶级的基类Object的源码。该源码中包含了12个方法,那我们在开发的过程中常用的方法有5个,线程类中常用的有5个。剩下的finalize已经在jdk9中被标记deprecated,registerNatives是加载本地方法用的,用C语言开发的,咱们也不常用。

equalsignorecase

上面简单的三行代码就是Object类中equals的源码。主要的比较是两个对象的地址。可以看到,方法体中equals比较其实也是“==”实现的。因此,下次在面试的过程中,你遇见问equals与“==”的区别的时候,你先给出结论。==是比较两个对象地址的,没有重写equals方法的实体类使用equals也是比较地址的。

那么我们经常用String中equals为什么是比较值的呢?接下来我们看一下String类中equals的源码

在我们实际编写代码的时候,特别是一些需要重写equals方法的实体类的时候,那么我们需要进行equals的方法重写,重写equals方法需要遵守如下约定。翻译如下

(1)自反性:x.equals(x)必须返回true。


(2)对称性:x.equals(y)与y.equals(x)的返回值必须相等。


(3)传递性:x.equals(y)为true,y.equals(z)也为true,那么x.equals(z)必须为true。


(4)一致性:如果对象x和y在equals()中使用的信息都没有改变,那么x.equals(y)值始终不变。


(5)非null:x不是null,y为null,则x.equals(y)必须为false。

这就涉及到我们上述在Obejct中看到的另一个方法。细心的朋友可能发现了,hashCode方法的修饰符是native。在Object类中有7个方法都是native修饰的。而在String类中hashCode源码如下。可以看到。该hashCode方法返回的是一个整形。它主要计算的是一个字符串的hash值然后将其缓存从而提高其性能,而计算的算法在注释中有提。那就是s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1],算法中31是因为JVM对其进行了优化处理,即:31 * i == (i << 5) - i

重写hashCode的原则如下,也是我们必须遵守的,就等同于重写equals方法一样也需要遵守原则

(1)如果重写了equals()方法,检查条件“两个对象使用equals()方法判断为相等,则hashCode()方法也应该相等”是否成立,如果不成立,则重写hashCode ()方法。


(2)hashCode()方法不能太过简单,否则哈希冲突过多。


(3)hashCode()方法不能太过复杂,否则计算复杂度过高,影响性能。

其实,简单的来说。在我们重写hashCode方法的时候,我们一般会根据自身的业务来进行hashCode算法编写。正如String方法中的hashCode计算算法一样。我们根据业务涉及出自己所需要的算法。

其实有些人说的,重写了equals方法就一定要重新hashCode。这句话其实是错的

因为hashCode和equals没有必然的区别。因为如果你不需要使用你定义的对象进行散列存储,比如使用hashMap,hashSet等集合,你不重写也没关系。因为hashCode本身是用来根据算法计算对象的散列值,然后根据这个值来决定存放位置。

举个简单的例子,如果使用HashMap,那么要保证key唯一,也就是要让其不重复,在java中比较是否相等用equals吧,所以使用equals去进行挨个比较,如果容器中已经存放了多个Key,是不是就需要比较很多次呢?如果有了hashCode值,是不是就简单多了。其实可以看一下hashmap的关于key比较的源码,就一清二楚了。在HashMap源码的625行putVal方法中可以看到634行及以后的内容,hashMap在put值的时候,其实首先用==去比较的是key的hash值。然后再用equals方法。

最后,也是最重要的一点,如果你重写了equals方法,在set,或hashmap容器中使用的时候,两个相等的对象有可能有不同的hashCode,这样就会导致容器中存放两个相同的对象,导致调用容器的方法出现逻辑错误。导致你的equals方法写了也白写,没有起到根本的作用。

又因为容器在我们日常开发中经常用到,因此才有了重写equals建议重写hashCode。也只是建议!

标签: 源码     Java     equals