Java中equals和hashcode的区别

2023-08-02 15:03:21 浏览数 (3)

==equalshashcode 的作用类似,但也各有不同。

# 1. Jvava ==

== 运算符用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能使用 “==” 运算符。

具体而言,如果两个变量是基本数据类型,那么可以直接使用 “==” 运算符来比较其对应的值是否相等。如果一个变量指向的数据是对象(引用类型),那么,此时涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存。

例如,对于赋值语句 String s=new String (),变量 s 占用一块存储空间,而 new String () 则存储在另外一块存储空间里,此时,变量 s 所对应的内存中存储的数值就是对象占用的那块内存的首地址。

对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,那么要看这两个变量所对应的内存中的数值是否相等(这两个对象是否指向同一块存储空间),这时候就可以用 “” 运算符进行比较。但是,如果要比较这两个对象的内容是否相等,那么用 “” 运算符就无法实现了。

# 2. Java equals

equals 是 Object 类提供的方法之一,因为每一个 Java 类都继承自 Object 类,所以每一个对象都具有 equals 这个方法。因为 Object 类中定义的 equals (Object) 方法是直接使用 “” 运算符比较的两个对象,所以在没有覆盖 equals (Object) 方法的情况下,equals (Object) 与 “” 运算符一样,比较的是引用。

相比 “==” 运算符,因为 equals (Object) 方法的特殊之处就在于它可以被覆盖,所以可以通过覆盖的方法让它不是比较引用而是比较数据内容。

例如 String 类的 equals 方法是用于比较两个独立对象的内容是否相同,即堆中的内容是否相同。例如,对于下面的代码:

代码语言:javascript复制
String s1 = new String("Hello");
String s2 = new String("Hello");

两条 new 语句创建了两个对象,然后用 s1、s2 这两个变量分别指向了一个对象,这是两个不同的对象,它们的首地址是不同的,即 a 和 b 中存储的数值是不相同的,所以,表达式 a==b 将返回 false,而这两个对象中的内容是相同的,所以,表达式 a.equals (b) 将返回 true。

如果一个类没有自己定义 equals 方法,那么它将继承 Object 类的 equals 方法,Object 类的 equals 方法的实现代码如下所示:

代码语言:javascript复制
boolean equals(Object o){    
    return this == o;
}

通过以上例子可以看出,如果一个类没有自己定义 equals 方法,那么它默认的 equals 方法(从 Object 类继承的)就是使用 “” 运算符,也是在比较两个变量指向的对象是否是同一对象,此时使用 equal 方法和使用 “” 运算符会得到同样的结果,如果比较的是两个独立的对象,那么返回 false。

如果编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么必须覆盖 equals 方法,由开发人员自己写代码来决定在什么情况即可认为两个对象的内容是相同的。

# 3. Java hashCode

hashCode() 方法是从 Object 类中继承过来的,它也用来鉴定两个对象是否相等。

Object 类中的 hashCode () 方法返回对象在内存中地址转换成的一个 int 值,所以如果没有重写 hashCode () 法,那么任何对象的 hashCode () 方法都是不相等的。

虽然 equals 方法也是用来判断两个对象是否相等的,但是二者是有区别的。一般来讲,equals 方法是给用户调用的,如果需要判断两个对象是否相等,那么可以重写 equals 方法,然后在代码中调用,就可以判断它们是否相等了。

对于 hashCode () 方法,用户一般不会去调用它,例如在 hashmap 中,由于 key 是不可以重复的,它在判断 key 是否重复的时候就判断了 hashCode () 这个方法,而且也用到了 equals 方法。此处 “不可以重复” 指的是 equals 和 hashCode () 只要有一个不等就可以了。所以,hashCode () 相当于是一个对象的编码,就好像文件中的 md5,它与 equals 方法的不同之处就在于它返回的是 int 型,比较起来不直观。

一般在覆盖 equals 方法的同时也要覆盖 hashCode () 方法,否则,就会违反 Object.hashCode 的通用约定,从而导致该类无法与所有基于散列值 (hash) 的集合类(HashMap、HashSet 和 Hashtable)结合在一起正常运行。

hashCode () 方法的返回值和 equals 方法的关系如下所示:

  • 如果 x.equals (y) 返回 true,即两个对象根据 equals 方法比较是相等的,那么调用这两个对象中任意一个对象的 hashCode () 方法都必须产生同样的整数结果。
  • 如果 x.equals (y) 返回 false,即两个对象根据 equals () 方法比较是不相等的,那么 x 和 y 的 hashCode () 方法的返回值有可能相等,也有可能不等。反过来,hashCode () 方法的返回值不等,一定能推出 equals 方法的返回值也不等,而 hashCode () 方法的返回值相等,equals 方法的返回值则可能相等,也可能不等。

1 人点赞