前几天看了篇关于java中equals和hashCode方法的解析

1、Object类中的equals方法和hashCode方法。

Object类中的equals和hashCode方法简单明了,所有的类都继承了这两个方法,只是有些类(String、Integer等)会重写这两个方法实现自己的更详细功能,之后会重点介绍。

① equals():

1
2
3
public boolean equals(Object obj) {
        return (this == obj);    
}
②hashCode():
1
public native int hashCode();
1
 
1
equals方法比较两个对象的引用(地址)是否相等,hashCode调用的是本地的方法,实质上对象调用hashCode方法返回的是对象引用(地址)的值。这样若equals方法返回为true,这两个引用一定是相等的,hashCode方法返回的值也就是相等的。
1
  
1
  
1
<SPAN style="FONT-SIZE: medium"><STRONG> 2、其他类中重写的equals方法和hashCode方法。</STRONG></SPAN>
1
 
1
java类库中很多类都重写了Object中的这两个方法,实现了自己更详细的功能,比如String类中重写equals之后,保证了即使对象引用不同,但是字符串的内容相同,也同样返回为true,也被认为是两个字符串对象是相等的,这在语义上也更符合人类的思维.比如:
1
2
3
4
        String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1.equals(str2));//返回true
System.out.println(str1 == str2); //返回false
1
 
1
  
1
在这段代码中str1 和 str2 是保存的不同的引用的,但是字符串的内容是相同的,都是“abc”(其实“abc”在String类中是以字符数组保存的,喜欢看java源代码,了解类的内部实现的童鞋应该很了解吧,推荐大家在用一个类的时候多看它的源代码,很多实现的原理都可以找到,并且能够学到很棒的类的设计和算法的实现-_-)。使用 == 比较的则是两个地址是否相等,当然返回的是false.但是使用String类中重写的equals方法便能够判断两个对象内部的字符串是相同的,也理所当然的返回true.
1
  
1
下面给出String类中这两个方法的实现:
1
  
1
①equals():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String) anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
1
②hashCode():
1
2
3
4
5
6
7
8
9
10
11
12
public int hashCode() {
     int h = hash;
     if (h == 0 && value.length > 0) {
         char val[] = value;
 
         for (int i = 0; i < value.length; i++) {
             h = 31 * h + val[i];
         }
         hash = h;
     }
     return h;
 }
1
  
1
从上面两个方法我们可以了解到很多东西,equals方法首先判断了两个引用是否相等,如果相等直接return true,这是必须的,引用都相等了肯定是同一个对象.如果引用不相等,并没有结束,而是继续判断是不是String类的实例,如果是,检测对象中字符串数组的每一个元素是否相同,如果相同那么就返回true,判定为相等。
1
  
1
在看hashCode方法,String类中也重写了hashCode方法,其中返回一个int型数据,可以看出是根据字符串数组中的元素计算出来的一个值。试想一下,如果equals方法返回为true,那说明这个String对象里面的内容是一样的,hashCode方法根据内容计算的返回的值也当然是相同的了。
1
  
1
不知各位发现了没有,对于equals返回为true的两个对象,hashCode方法返回的值也一定是相同的(对于Object类,equals返回true表示地址相同,hashCode正好是返回地址,必定相同。对于String类,equals返回true表示内容相同,hashCode根据内容返回一个值,也必定是相同的)。
1
  
1
但是反过来成立么,对于hashCode返回值相同的对象,equals返回一定是true吗?思考一下,答案是否定的。因为String类中的hashCode是根据字符数组的元素经过一系列复杂计算得出的,会不会有这种情况,hashCode的返回值相同,但是字符串的内容错位差那么一点(就是字符串的元素不完全相同,但是经过计算恰好保证了hashCode相同),这点概率还是有的。所以上面的那句话是不成立的,这里可能有点难以理解,静下心来仔细想想.
1
  
1
再来一句话,hashCode返回值不同的对象,equals返回一定是false,对否? ……这个通过上面的红字应该可以推理得到吧。hashCode返回不同,但是equals返回为true,可能吗..equals返回为true,hashCode就一定相等了好么亲爱的。所以这句话是对的。
1
  
1
我们还应该注意,Java语言对equals()的要求如下,这些要求是必须遵循的:
1
  

• 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。

• 反射性:x.equals(x)必须返回是“true”。

• 类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。

• 还有一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。

• 任何情况下,x.equals(null),永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”。

通过上面的分析,可以得出一个重要的类设计思想,equals方法返回为true的两个对象,一定要保证hashCode返回值相等。Object类中保证了,String类中保证了,大家可以去看Double类,Integer类就会返现,都保证了这一点,hashCode都是与内容有关的。在自己编码设计类的过程中,如果要重写equals方法,进行自己的必要,也要注意同时重写Object的hashCode方法,保证这一点。

上实例,要求设计一个Student类,重写equals方法和hashCode方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Student
  
{
  
    int num;
  
    String name;
  
    Student(int num, String name)
  
    {
  
        this.num = num;
  
        this.name = name;
  
    }
  
    public int hashCode()
  
    {
  
        return num * name.hashCode();
  
    }
  
    public boolean equals(Object o)
  
    {
  
        if(this == o)
        {
            return true;
        }
          
        Student s = (Student) o;
  
        return num == s.num && name.equals(s.name);
  
    }
  
    public String toString()
  
    {
  
        return num + ":" + name;
  
    }
  
}

看上面这个例子是否能够满足前面谈到的要注意的几点?

若两个Student对象学号和名字一样能否返回true?

若equals方法返回true,hashCode返回值是否相等?

总结:①Object类中有自己的equals和hashCode方法,String等类进行了重写,可以判断内容是否真正相等。

          ②重写equals方法必须同时重写与之相配的hashCode方法。 

          ③equals返回为true的两个对象,hashCode返回的值必须是相同的。

          ④hashCode返回值相同,equals不一定返回true。

          ⑤hashCode返回值不相同,equals一定返回的是false。

谈到这两个方法不得不提到集合类中Hash那一辈,下一篇博文将详细讲解和理清集合类中是如何通过这两个方法,保证集合中的元素不重复的,会利用hashCode方法和equals方法从内部了解其中比较的技巧.

java中equals和hashCode方法随笔二的更多相关文章

  1. java中equals和hashCode方法的解析

    解析Java对象的equals()和hashCode()的使用 前言 在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,就要设计另外一个.在多 ...

  2. Java中equals和hashcode的区别?

    Java中equals和hashcode方法是在Object对象中的,所以每个对象都有这两个方法,大多数时候我们为了实现特定需求需要重写这两个方法 equals和hashcode方法常用在同一个类中用 ...

  3. java重写equals和hashCode方法

    一.重写equals方法 如果不重写equals,那么比较的将是对象的引用是否指向同一块内存地址,重写之后目的是为了比较两个对象的value值是否相等. 利用equals比较八大包装对象(如int,f ...

  4. Java中equals,hashcode

         在Java语言中,Object对象中包含一个equals和hashCode方法,其中hashCode方法是由JVM本地代码(native code)实现的,返回值是一个有符号的32位整数,对 ...

  5. 【Java】equals()与hashCode()方法详解 (转)

    java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...

  6. Java中equals()和hashCode()的关系以及重写equals()和hashCode()的重要性

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6580647.html  一:关系 如果两个对象相等(equal),它们的hashcode一定相同: 如果两个对 ...

  7. java中equals与hashCode的重写问题

    这几天有一个朋友问我在重写equals和hashCode上出现了问题,最后我帮她解决了问题,同时也整理出来分享给大家 现上Object的equals与HashCode的代码 public boolea ...

  8. Java 重写equals()与hashCode()方法

    List对象的contains方法实际上也是调用的equals()方法来进行逐条对比的. 示例代码: package com.imooc.collection; /** * 课程类 */ public ...

  9. Java中equals,hashcode,==的区别

    ==  :比较java栈局部变量表中变量的地址或值是否相等. equals : 比较变量的地址在java堆中引用对象是否为同一个对象. hashcode : 通过对象在JVM内存中的存储地址通过特定算 ...

随机推荐

  1. SQL Server数据库log shipping 灾备(Part1 )

    1.概述 Log Shipping为SQL Server提供的数据库备份过程.它可以将数据库整个复制到另一台服务器上.在这种情况下,交易日志也会定期发送到备份服务器上供恢复数据使用,这使得服务器一直处 ...

  2. SQL Server 2012安装配置(Part3 )

    SQL Server 2012安装配置(Part1 ) SQL Server 2012安装配置(Part2 ) SQL Server 2012安装配置(Part3 ) 3 客户端安装 3.1 安装客户 ...

  3. 使用代码获得Netweaver里某个software component和C4C的版本

    有同事问如何通过代码的方式获得Netweaver里某个Software component的版本信息,以及Cloud for Customer(C4C)的版本信息. Netweaver 点了Detai ...

  4. 卓越管理的实践技巧(3)推动团队管理的要点 Facilitation Essentials for Managers

    Facilitation Essentials for Managers 前文卓越管理的秘密(Behind Closed Doors)最后一部分提到了总结的13条卓越管理的实践技巧并列出了所有实践技巧 ...

  5. Oracle CRS/GI 进程介绍

    在10g和11.1,Oracle的集群称为CRS(Oracle Cluster Ready Service), 在11.2,Oracle的集群称为GI(Grid Infrastructure). 对于 ...

  6. python_105_类的特殊成员方法

    aa.py class C(): def __init__(self): self.name='QiZhiguang' 类的特殊成员方法: # 1. __doc__ 表示类的描述信息 class Do ...

  7. sklearn 学习之分类树

    概要 基于 sklearn 包自带的 iris 数据集,了解一下分类树的各种参数设置以及代表的意义.   iris 数据集介绍 iris 数据集包含 150 个样本,对应数据集的每行数据,每行数据包含 ...

  8. DROP OPERATOR - 删除一个操作符

    SYNOPSIS DROP OPERATOR name ( lefttype | NONE , righttype | NONE ) [ CASCADE | RESTRICT ] DESCRIPTIO ...

  9. ssh整合思想初步 struts2与Spring的整合 struts2-spring-plugin-2.3.4.1.jar下载地址 自动加载Spring中的XML配置文件 Struts2下载地址

    首先需要JAR包 Spring整合Structs2的JAR包 struts2-spring-plugin-2.3.4.1.jar 下载地址 链接: https://pan.baidu.com/s/1o ...

  10. vuePress的使用

    今天来玩一玩vuePress的使用,用markdown来编辑一个页面网站,这里谈论到了简单使用,细节可以去官网上去查看 开始安装 项目依赖 // package.json { "name&q ...