Java 中的 ==, equals 与 hashCode 的区别与联系

概述

  • == : 该操作符生成的是一个boolean结果,它计算的是操作数的值之间的关系
  • equals : Object 的 实例方法,比较两个对象的content是否相同
  • hashCode : Object 的 native方法 , 获取对象的哈希值,用于确定该对象在哈希表中的索引位置,它实际上是一个int型整数

关系操作符 ==

基本数据类型变量

在Java中有八种基本数据类型:

  • 浮点型:float(4 byte), double(8 byte)
  • 整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)
  • 字符型: char(2 byte)
  • 布尔型: boolean(JVM规范没有明确规定其所占的空间大小,仅规定其只能够取字面值”true”和”false”)

对于这八种基本数据类型的变量,变量直接存储的是“值”。因此,在使用关系操作符 == 来进行比较时,比较的就是“值”本身。要注意的是,浮点型和整型都是有符号类型的(最高位仅用于表示正负,不参与计算【以 byte 为例,其范围为 -2^7 ~ 2^7 - 1,-0即-128】),而char是无符号类型的(所有位均参与计算,所以char类型取值范围为0~2^16-1)

引用类型变量

在Java中,引用类型的变量存储的并不是“值”本身,而是与其关联的对象在内存中的地址。
str1= new String("hello");
这个 str1 就指向了这个对象,此时引用变量str1中存储的是它指向的对象在内存中的存储地址,并不是“值”本身,也就是说并不是直接存储的字符串”hello”。这里面的引用和 C/C++ 中的指针很类似。

小结

因此,对于关系操作符 ==:

  • 若操作数的类型是基本数据类型,则该关系操作符判断的是左右两边操作数的值是否相等
  • 若操作数的类型是引用数据类型,则该关系操作符判断的是左右两边操作数的内存地址是否相同。也就是说,若此时返回true,则该操作符作用的一定是同一个对象。

equals方法

来源

equals方法是基类Object中的实例方法,因此对所有继承于Object的类都会有该方法。  
在 Object 中的声明:
public boolean equals(Object obj) {}

equals方法的作用

初衷 : 判断两个对象的 content 是否相同
使用equals方法,内部实现分为三个步骤:

  • 先比较引用是否相同(是否为同一对象),
  • 再判断类型是否一致(是否为同一类型,
  • 最后比较内容是否一致

Java 中所有内置的类的 equals 方法的实现步骤均是如此,特别是诸如 Integer,Double 等包装器类。

hashCode 方法

来源

hashCode 方法是基类Object中的 实例native方法,因此对所有继承于Object的类都会有该方法。

在 Object类 中的声明(native方法暗示这些方法是有实现体的,但并不提供实现体,因为其实现体是由非java语言在外面实现的)
public native int hashCode();

作用

HashCode 只是在需要用到哈希算法的数据结构中才有用,比如 HashSet, HashMap 和 Hashtable。

Java中的集合(Collection)有三类,一类是List,一类是Queue,再有一类就是Set。 前两个集合内的元素是有序的,元素可以重复;最后一个集合内的元素无序,但元素不可重复。

那么, 这里就有一个比较严重的问题:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢? 这就是 Object.equals 方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。 也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。于是,Java采用了哈希表的原理。 这样,我们对每个要存入集合的元素使用哈希算法算出一个值,然后根据该值计算出元素应该在数组的位置。所以,当集合要添加新的元素时,可分为两个步骤:

  • 先调用这个元素的 hashCode 方法,然后根据所得到的值计算出元素应该在数组的位置。如果这个位置上没有元素,那么直接将它存储在这个位置上
  • 如果这个位置上已经有元素了,那么调用它的equals方法与新元素进行比较:相同的话就不存了,否则,将其存在这个位置对应的链表中(Java 中 HashSet, HashMap 和 Hashtable的实现总将元素放到链表的表头)

你可能感兴趣的:(Java 中的 ==, equals 与 hashCode 的区别与联系)