前几天看了篇关于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. SharePoint Server 2016 WEB 网站浏览器支持

    SharePoint Server 2016支持多种常用的Web浏览器,如Internet Explorer,Google Chrome,Mozilla Firefox,Apple Safari和Mi ...

  2. Outlook Web App 客户端超时设置

    这篇文章我们讨论一下,OWA 2013在公共和私人的电脑是如何启用和配置. Exchange 2013 Outlook Web App (OWA) 登录页不再允许用户选择无论他们正在使用公共的或私人的 ...

  3. Locust安装教程与使用

    Locust安装教程与使用官网地址:https://github.com/locustio/locust 如果是python3+以上的环境,需要下载locust项目源码进行安装 因Centos7.2环 ...

  4. pc端常见布局---垂直居中布局 单元素不定高

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  5. odoo前端

    bootstrap: http://www.runoob.com/bootstrap/bootstrap-tutorial.html javascript: http://www.runoob.com ...

  6. 13Shell脚本—编写简单脚本

    1. 概述 Shell脚本命令的工作方式有两种:交互式和批处理. 交互式(Interrctive): 用户每输入一条命令就立即执行. 批处理(Batch): 由用户事先编写好一个完整的 Shell 脚 ...

  7. Linux 安装Nginx+PHP+MySQL教程

    一.安装nginx 通过yum安装openssl: yum -y install openssl openssl-devel 通过yum安装pcre: yum -y install pcre-deve ...

  8. python-数据类型总结 (面试常问)

    目录 数字类型总结 拷贝 浅拷贝 深拷贝 数字类型总结 一个值 多个值 整型/浮点型/字符串 列表/字典/元祖/集合 有序 无序 字符串/列表/元祖 字典/集合 可变 不可变 列表/字典/集合 整型/ ...

  9. 收集的有关mdk 3的使用方法

      收集来自网络上的有关mdk3的一些使用方法以及技巧(持续更新) b beacon泛洪攻击 -f 指定wifi名称的文件夹 -n 加上wifi名称 -w Fake WEP encrypted sta ...

  10. Applied Nonparametric Statistics-lec1

    参考网址: https://onlinecourses.science.psu.edu/stat464/node/2 Binomial Distribution Normal Distribution ...